Patch for ldap-odm, Jul 13

This commit is contained in:
Mattias Arthursson
2007-07-13 07:27:19 +00:00
parent 4f3c0fd930
commit 795ecdf61c
28 changed files with 1768 additions and 361 deletions

View File

@@ -19,7 +19,7 @@
<import file="${common.build.dir}/itest-targets.xml" />
<import file="${common.build.dir}/doc-targets.xml" />
<import file="${common.build.dir}/clover-targets.xml" />
<import file="${common.build.dir}/jdiff-targets.xml" />
<import file="${common.build.dir}/jdiff-targets.xml" />
<!-- extend common-build with source capability -->
<target name="build.prepare.make.config.dirs" depends="common-targets.build.prepare.make.config.dirs">
@@ -31,7 +31,8 @@
-->
<target name="tests" depends="tests-local,test-report,itests,itest-report" description="Runs all tests, first local then server (if any)" />
<!--
<!--
Overridden only to have the errorproperty and failureproperty attributes
added to the junit task.
-->
@@ -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. -->
<junit forkmode="perBatch" printsummary="yes" haltonfailure="no" haltonerror="no" dir="${basedir}" errorproperty="tests.failed" failureproperty="tests.failed">
<junit forkmode="perBatch" printsummary="yes" haltonfailure="no" haltonerror="no" dir="${basedir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true">
<jvmarg value="${unitvm}" />
<jvmarg value="-Djava.security.auth.login.config=${target.testclasses.dir}/auth.conf" />
<jvmarg value="${test.arguments}" />
@@ -64,7 +65,7 @@
</target>
<property name="target.testresults.html.dir" location="${target.testresults.dir}/html" />
<!-- Generate the unit test report -->
<target name="test-report" depends="build.prepare" description="Generate HTML report of unit test results">
<delete dir="${target.testresults.html.dir}" />
@@ -82,4 +83,13 @@ The HTML report is ${target.testresults.html.dir}/index.html
<fail if="tests.failed" message="Unit tests failed" />
</target>
<target name="clover-report" depends="clover.instrument, tests-local" description="Produce a test coverage report">
<clover-report>
<current outfile="${target.clover.dir}/coverage.xml" />
<current outfile="${target.clover.dir}/html">
<format type="html" />
</current>
</clover-report>
</target>
</project>

View File

@@ -22,7 +22,7 @@
<dependency org="commons-logging" name="commons-logging" rev="1.0.4" />
<dependency org="commons-lang" name="commons-lang" rev="2.1" />
<dependency org="commons-collections" name="commons-collections" rev="3.1" />
<dependency org="org.springframework" name="spring-ldap" rev="latest.integration"/>
<dependency org="org.springframework" name="spring-ldap" rev="latest.integration"/>
<dependency org="org.springframework" name="spring-beans" rev="2.0.4"/>
<dependency org="org.springframework" name="spring-core" rev="2.0.4"/>
<dependency org="org.springframework" name="spring-context" rev="2.0.4"/>
@@ -31,14 +31,14 @@
<artifact name="spring-src" type="zip"/>
</dependency>
<dependency org="com.sun" name="ldapbp" rev="1.0" />
<dependency org="xstream" name="xstream" rev="1.2" />
<dependency org="xstream" name="xstream" rev="1.2" />
<!-- build time only dependencies -->
<dependency org="org.tigris" name="svnant" rev="1.0.0" conf="buildtime->default">
<artifact name="svnant" type="jar"/>
<artifact name="svnClientAdapter" type="jar"/>
<artifact name="svnjavahl" type="jar"/>
</dependency>
<dependency org="org.tigris" name="svnant" rev="1.0.0" conf="buildtime->default">
<artifact name="svnant" type="jar"/>
<artifact name="svnClientAdapter" type="jar"/>
<artifact name="svnjavahl" type="jar"/>
</dependency>
<!-- test time only dependencies -->
<dependency org="com.cenqua.clover" name="clover" rev="1.3.12" conf="test->default" />
@@ -48,9 +48,11 @@
<dependency org="junit" name="junit" rev="3.8.1" conf="test->default"/>
<dependency org="junit-addons" name="junit-addons" rev="1.4" conf="test->default"/>
<dependency org="junitperf" name="junitperf" rev="1.8" conf="test->default"/>
<dependency org="easymock" name="easymock" rev="1.2_Java1.3" conf="test->default"/>
<dependency org="cglib" name="cglib-nodep" rev="2.1_3" conf="test->default"/>
<dependency org="org.testng" name="testng" rev="5.0" conf="test->default" />
<dependency org="easymock" name="easymock" rev="2.0" conf="test->default"/>
<dependency org="easymock" name="easymockclassextension" rev="1.2" conf="test->default"/>
<dependency org="cglib" name="cglib-nodep" rev="2.1_3" conf="test->default"/>
<dependency org="org.testng" name="testng" rev="5.0" conf="test->default" />
<!-- Test dependencies for Apache Directory Server -->
<dependency org="org.apache.directory.server" name="apacheds-core" rev="1.0.0"
@@ -74,8 +76,8 @@
<dependency org="org.apache.directory.shared" name="shared-asn1" rev="0.9.5.3"
conf="test->default"/>
<dependency org="org.apache.directory.shared" name="shared-asn1-codec" rev="0.9.5.3"
conf="test->default"/>
<dependency org="org.apache.directory.shared" name="shared-asn1-codec" rev="0.9.5.3"
conf="test->default"/>
<dependency org="org.apache.directory.shared" name="shared-ldap" rev="0.9.5.3"
conf="test->default"/>
@@ -91,5 +93,5 @@
<!-- End test dependencies for Apache Directory Server -->
</dependencies>
</ivy-module>

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This context automatically starts the Apache Directory Server
and sets up the test data
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- JNDI environment variable -->
<bean id="environment"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="java.naming.security.authentication">
simple
</prop>
<prop key="java.naming.security.principal">
${userDn}
</prop>
<prop key="java.naming.security.credentials">
${password}
</prop>
</props>
</property>
</bean>
<!--
Note the non-standard port, in order to leave 389 unused, thus
making it easier for the integration tests requiring OpenLDAP.
-->
<bean id="configuration" class="org.apache.directory.server.configuration.MutableServerStartupConfiguration">
<property name="ldapPort" value="3900" />
<property name="contextPartitionConfigurations">
<set>
<ref bean="jaywayPartitionConfiguration"/>
</set>
</property>
</bean>
<bean id="jaywayPartitionConfiguration"
class="org.apache.directory.server.core.partition.impl.btree.MutableBTreePartitionConfiguration">
<property name="name" value="example" />
<property name="suffix" value="dc=example,dc=com" />
<property name="contextEntry">
<value>
objectClass: top
objectClass: domain
objectClass: extensibleObject
dc: example
</value>
</property>
</bean>
<bean id="configEnvHelper" class="org.springframework.ldap.ConfigEnvHelper">
<constructor-arg ref="environment" />
<constructor-arg ref="configuration" />
</bean>
<bean name="serverContext" class="javax.naming.InitialContext">
<constructor-arg>
<bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetObject" ref="configEnvHelper" />
<property name="propertyPath" value="env" />
</bean>
</constructor-arg>
</bean>
<bean name="ldapServerManager" class="org.springframework.ldap.LdapServerManager">
<property name="contextSource" ref="contextSource" />
</bean>
<!-- Custom editors required to launch ApacheDS -->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="javax.naming.directory.Attributes">
<bean class="org.apache.directory.server.core.configuration.AttributesPropertyEditor"/>
</entry>
</map>
</property>
</bean>
</beans>

View File

@@ -2,12 +2,20 @@
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://localhost:10389"/>
<property name="base" value="dc=example,dc=com"/>
<property name="userName" value="cn=Directory Manager"/>
<property name="password" value="password"/>
</bean>
<import resource="classpath:/conf/apacheDsContext.xml"/>
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/conf/ldap.properties" />
</bean>
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource" >
<property name="urls" value="${urls}" />
<property name="userDn" value="${userDn}" />
<property name="password" value="${password}" />
<property name="base" value="${base}" />
<property name="dirObjectFactory" value="org.springframework.ldap.core.support.DefaultDirObjectFactory" />
</bean>
<bean id="ldapTemplate" singleton="true" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource"/>

View File

@@ -0,0 +1,4 @@
urls=ldap://127.0.0.1:3900
userDn=uid=admin,ou=system
password=secret
base=dc=example,dc=com

View File

@@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/docs/api/org/apache/log4j/xml/log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<!-- <param name="ConversionPattern" value="[%d{dd/MMM/yyy:HH:mm:ss:SS}] [%t] [%x] %-5p %c{1} - %m %n"/> -->
<param name="ConversionPattern" value="[%t] [%x] %-5p %c{1} - %m %n"/>
</layout>
</appender>
<appender name="file" class="org.apache.log4j.FileAppender">
<param name="file" value="odm.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd/MMM/yyy:HH:mm:ss:SS}] [%t] [%x] %-5p %c{1} - %m %n"/>
</layout>
</appender>
<logger name="org.springframework.beans">
<level value="warn"/>
<appender-ref ref="console"/>
</logger>
<logger name="org.springframework.context">
<level value="warn"/>
<appender-ref ref="console"/>
</logger>
<logger name="org.apache.directory">
<level value="error"/>
<appender-ref ref="console"/>
</logger>
<logger name="org.springframework.core">
<level value="warn"/>
<appender-ref ref="console"/>
</logger>
<logger name="org.springframework.ldap.core">
<level value="info"/>
<appender-ref ref="console"/>
</logger>
<logger name="org.springframework.ldap.odm">
<level value="debug"/>
<appender-ref ref="console"/>
</logger>
</log4j:configuration>

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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());
}
}

View File

@@ -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
}
}
}
}

View File

@@ -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<example", "dc=com"})
@ObjectClasses({"top", "person", "organizationalPerson", "inetorgperson"})
public class MockModelNamingSuffixSyntaxError
{
}
@NamingAttribute("cn")
@NamingSuffix({"ou=people", "dc=example", "dc=com"})
@ObjectClasses({"top", "person", "organizationalPerson", "inetorgperson"})
public class MockModelInvalidTranslationType
{
@DirAttribute("fred")
private Map map;
public Map getMap()
{
return map;
}
public void setMap(Map map)
{
this.map = map;
}
}
}

View File

@@ -5,42 +5,44 @@
*/
package org.springframework.ldap.odm.dao;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.ldap.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.NameAlreadyBoundException;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.odm.dao.exception.DataIntegrityViolationException;
import org.springframework.ldap.odm.dao.exception.EntryNotFoundException;
import org.springframework.ldap.odm.entity.TestPerson;
import org.springframework.ldap.odm.entity.TestRole;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.List;
public class LdapDaoTest
public class LdapDaoTest extends AbstractLdapTemplateIntegrationTest
{
protected static final Log LOGGER = LogFactory.getLog(LdapDaoTest.class);
protected LdapDao ldapDao;
private ClassPathXmlApplicationContext applicationContext;
private TestPerson testPerson;
private TestRole validRole;
@BeforeClass(alwaysRun = true)
public void initTestClass()
protected String[] getConfigLocations()
{
LOGGER.debug("********************INIT TEST CLASS**************************");
applicationContext = new ClassPathXmlApplicationContext("beans.xml");
ldapDao = (LdapDao) applicationContext.getBean("ldapDao");
return new String[]{"beans.xml"};
}
protected void onSetUp() throws Exception
{
super.onSetUp();
createPerMethodConsumer();
}
public void setLdapDao(LdapDao ldapDao)
{
this.ldapDao = ldapDao;
}
@BeforeMethod(alwaysRun = true)
public void createPerMethodConsumer()
{
LOGGER.debug("********************CREATE PER METHOD CONSUMER**************************");
@@ -53,18 +55,7 @@ public class LdapDaoTest
testPerson.setPassword("test1234".getBytes());
}
@BeforeClass(alwaysRun = true)
public void createValidRole()
{
LOGGER.debug("********************CREATE VALID ROLE**************************");
validRole = new TestRole();
validRole.setRoleName("webUser");
validRole.setDescription("A valid role");
}
@Test(groups = "LdapDao")
public void createEntity()
public void testCreateEntity()
{
try
{
@@ -76,8 +67,8 @@ public class LdapDaoTest
}
}
@Test(groups = "LdapDao")
public void createOrUpdateEntity()
public void testCreateOrUpdateEntity()
{
try
{
@@ -91,8 +82,7 @@ public class LdapDaoTest
}
@Test(groups = "LdapDao")
public void findByNamingAttribute()
public void testFindByNamingAttribute()
{
ldapDao.create(testPerson);
TestPerson retrieved = (TestPerson) ldapDao.findByNamingAttribute(testPerson.getIdentifier(), TestPerson.class);
@@ -100,18 +90,20 @@ public class LdapDaoTest
Assert.assertNotNull(retrieved, "Should've found the created entity.");
}
@Test(groups = "LdapDao")
public void findRoles()
public void testLoadsReferencedEntities()
{
TestRole webUser = (TestRole) ldapDao.findByNamingAttribute("webUser", TestRole.class);
ldapDao.create(testPerson);
validRole.setMembers(new TestPerson[]{testPerson});
ldapDao.createOrUpdate(validRole);
TestRole role = (TestRole) ldapDao.findByNamingAttribute("webUser", TestRole.class);
LOGGER.debug(role);
webUser.setMembers(new TestPerson[]{testPerson});
ldapDao.update(webUser);
TestRole updated = (TestRole) ldapDao.findByNamingAttribute("webUser", TestRole.class);
LOGGER.debug(updated);
Assert.assertTrue(ArrayUtils.contains(updated.getMembers(), testPerson));
}
@Test(groups = "LdapDao")
public void findByDn()
public void testFindByDn()
{
ldapDao.create(testPerson);
DistinguishedName dn = new DistinguishedName("uid=" + testPerson.getIdentifier() + ",ou=people");
@@ -121,8 +113,7 @@ public class LdapDaoTest
}
@Test(groups = "LdapDao")
public void createEntityThrowsExceptionWhenNameAlreadyBound()
public void testCreateEntityThrowsExceptionWhenNameAlreadyBound()
{
try
{
@@ -132,23 +123,20 @@ public class LdapDaoTest
}
catch (Exception expected)
{
Assert.assertTrue(expected instanceof DataIntegrityViolationException, "Exception type doesn't match expected. ( got: "
+ expected.getMessage());
Assert.assertTrue(expected.getMessage().contains("Name already bound"),
"Exception message doesn't match expected.");
Assert.assertTrue(expected instanceof NameAlreadyBoundException,
"Exception type doesn't match expected. ( got: "
+ expected.getMessage());
}
}
@Test(groups = "LdapDao")
public void findAll()
public void testFindAll()
{
ldapDao.create(testPerson);
List results = ldapDao.findAll(TestPerson.class);
Assert.assertTrue(results.size() > 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);

View File

@@ -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"})

View File

@@ -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);
}
}

View File

@@ -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:
* <li>
* <ul>convert from Generalized Time strings to java.util.Date</ul>
* <ul>convert dn strings to <code>javax.naming.ldap.LdapName</code> or
* <code>org.springframework.ldap.core.DistinguishedName</code>.
* </li>
*/
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];

View File

@@ -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 <code>LdapName.class</code> for String <--> LdapName and
* <code>DistinguishedName.class</code> 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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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<String, Method> propertyGetters;
private Map<String, Method> 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<String, Method>();
propertySetters = new HashMap<String, Method>();
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;
}
}

View File

@@ -17,20 +17,20 @@ import java.util.Map;
public class ContextMapperFactory
{
private static final Log LOGGER = LogFactory.getLog(ContextMapperFactory.class);
private Map<Class, AnnotatedClassContextMapper> contextMappers;
private Map<Class, AnnotationObjectDirectoryMapper> contextMappers;
private LdapTypeConverter typeConverter;
private ReferencedEntryEditorFactory referencedEntryEditorFactory;
public ContextMapperFactory(LdapTypeConverter typeConverter,
ReferencedEntryEditorFactory referencedEntryEditorFactory)
{
contextMappers = new HashMap<Class, AnnotatedClassContextMapper>();
contextMappers = new HashMap<Class, AnnotationObjectDirectoryMapper>();
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;
}

View File

@@ -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();
}

View File

@@ -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())

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}