Adding new framework ODM (object directory mapping).
This commit is contained in:
BIN
repository/org.testng/testng/5.0/testng-5.0.jar
Normal file
BIN
repository/org.testng/testng/5.0/testng-5.0.jar
Normal file
Binary file not shown.
169
spring-ldap-odm/build-original.xml
Normal file
169
spring-ldap-odm/build-original.xml
Normal file
@@ -0,0 +1,169 @@
|
||||
<project name="odm" basedir="." xmlns:ivy="antlib:fr.jayasoft.ivy.ant" default="info">
|
||||
|
||||
<xmlproperty file="build-properties.xml" keeproot="false" semanticattributes="true" collapseattributes="true"/>
|
||||
|
||||
<target name="-info">
|
||||
<echoproperties/>
|
||||
</target>
|
||||
|
||||
<taskdef resource="fr/jayasoft/ivy/ant/antlib.xml" uri="antlib:fr.jayasoft.ivy.ant">
|
||||
<classpath>
|
||||
<fileset dir="${config.ivy}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</classpath>
|
||||
</taskdef>
|
||||
|
||||
|
||||
<target name="-coverage.init" unless="coverage.init.done">
|
||||
<path id="coverage.classpath">
|
||||
<fileset dir="${build.lib.tasks}" includes="**/*.jar"/>
|
||||
</path>
|
||||
|
||||
<delete dir="${build.coverage.instrumented}"/>
|
||||
<delete dir="${build.coverage.output}"/>
|
||||
<delete dir="${build.coverage.reports}"/>
|
||||
<delete file="${build.coverage.datafile}"/>
|
||||
|
||||
<mkdir dir="${build.coverage.instrumented}"/>
|
||||
<mkdir dir="${build.coverage}"/>
|
||||
<mkdir dir="${build.coverage.output}"/>
|
||||
<mkdir dir="${build.coverage.reports}"/>
|
||||
|
||||
<delete dir="${build.coverage}"/>
|
||||
<mkdir dir="${build.coverage}"/>
|
||||
<property name="coverage.init.done" value="true"/>
|
||||
</target>
|
||||
|
||||
<target name="-coverage.instrument">
|
||||
<fail unless="build.coverage.datafile"/>
|
||||
<fail unless="build.main.classes"/>
|
||||
<fail unless="build.coverage.instrumented"/>
|
||||
<mkdir dir="${build.main.classes}"/>
|
||||
<mkdir dir="${build.coverage.instrumented}"/>
|
||||
|
||||
<cobertura-instrument datafile="${build.coverage.datafile}"
|
||||
toDir="${build.coverage.instrumented}">
|
||||
<fileset dir="${build.main.classes}"
|
||||
includes="**/*.class"/>
|
||||
</cobertura-instrument>
|
||||
</target>
|
||||
|
||||
<target name="-clean">
|
||||
<mkdir dir="${build}"/>
|
||||
<delete includeemptydirs="true" failonerror="false">
|
||||
<fileset dir="${build}">
|
||||
<include name="**/*"/>
|
||||
</fileset>
|
||||
</delete>
|
||||
</target>
|
||||
|
||||
<target name="-taskdef">
|
||||
<path id="tasks.lib">
|
||||
<fileset dir="lib">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
<taskdef resource="checkstyletask.properties" classpathref="tasks.lib"/>
|
||||
<taskdef resource="tasks.properties" classpathref="tasks.lib"/>
|
||||
<taskdef resource="testngtasks" classpathref="tasks.lib"/>
|
||||
</target>
|
||||
|
||||
<target name="-checkstyle">
|
||||
<mkdir dir="${build.checkstyle.reports}"/>
|
||||
<checkstyle config="${config.checkstyle}/main-checkstyle.xml" failonviolation="true">
|
||||
<formatter type="plain" toFile="${build.checkstyle.reports}/main-checkstyle-report.txt"/>
|
||||
<fileset dir="${source.main.java}">
|
||||
<include name="**/*.java"/>
|
||||
</fileset>
|
||||
<property key="checkstyle.import.control.file" value="main-import-control.xml"/>
|
||||
</checkstyle>
|
||||
|
||||
<checkstyle config="${config.checkstyle}/test-checkstyle.xml" failonviolation="true">
|
||||
<formatter type="plain" toFile="${build.checkstyle.reports}/test-checkstyle-report.txt"/>
|
||||
<fileset dir="${source.test.java}">
|
||||
<include name="**/*.java"/>
|
||||
</fileset>
|
||||
</checkstyle>
|
||||
</target>
|
||||
|
||||
<target name="-compile">
|
||||
<mkdir dir="${build.main.classes}"/>
|
||||
<mkdir dir="${build.test.classes}"/>
|
||||
<javac srcdir="${source.main.java}" destdir="${build.main.classes}" debug="true" fork="true" source="1.5"
|
||||
target="1.5">
|
||||
<classpath>
|
||||
<fileset dir="lib">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</classpath>
|
||||
</javac>
|
||||
<javac srcdir="${source.test.java}" destdir="${build.test.classes}" debug="true" fork="true" source="1.5"
|
||||
target="1.5">
|
||||
<classpath>
|
||||
<fileset dir="lib">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
<pathelement location="${build.main.classes}"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="-unit-test">
|
||||
<testng outputdir="${build.test.reports}" haltonfailure="false"
|
||||
failureproperty="unit.tests.failed">
|
||||
<sysproperty key="net.sourceforge.cobertura.datafile" file="${build.coverage.datafile}"/>
|
||||
<classpath>
|
||||
<pathelement location="${build.coverage.instrumented}"/>
|
||||
<pathelement location="${build.main.classes}"/>
|
||||
<pathelement location="${build.test.classes}"/>
|
||||
<pathelement location="${source.main.config}"/>
|
||||
<fileset dir="lib" includes="*.jar"/>
|
||||
</classpath>
|
||||
|
||||
<xmlfileset dir="${source.test.config}/testng" includes="unittest.xml"/>
|
||||
</testng>
|
||||
|
||||
<junitreport todir="${build.test.reports}">
|
||||
<fileset dir="${build.test.reports}/unit-tests" includes="*xml"/>
|
||||
<report format="noframes" todir="${build.test.reports}/unit-tests"/>
|
||||
</junitreport>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-cobertura-report">
|
||||
<cobertura-report datafile="${build.coverage.datafile}"
|
||||
srcdir="${source.main.java}"
|
||||
destdir="${build.coverage.reports}"/>
|
||||
</target>
|
||||
|
||||
<target name="-evaluate-build">
|
||||
<fail if="unit.tests.failed"/>
|
||||
<fail if="functional.tests.failed"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-package">
|
||||
<mkdir dir="${build.main.artifacts}"/>
|
||||
|
||||
<zip file="${build.main.artifacts}/odm-source.zip">
|
||||
<fileset dir="${source.main.java}" includes="**/*.java"/>
|
||||
</zip>
|
||||
|
||||
<jar file="${build.main.artifacts}/odm.jar">
|
||||
<fileset dir="${build.main.classes}" includes="**/*.class"/>
|
||||
</jar>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
<!-- private targets -->
|
||||
<target name="--info" depends="-info"/>
|
||||
<target name="--build"
|
||||
depends="-clean, -taskdef, -checkstyle, -compile, -package, -coverage.init, -coverage.instrument, -unit-test, -cobertura-report, -evaluate-build"/>
|
||||
|
||||
<!-- public targets -->
|
||||
<target name="info" depends="--info" description="-- echo the common and user specified build properties"/>
|
||||
<target name="build" depends="--build"
|
||||
description="-- clean, configure, compile and produce build artifacts"/>
|
||||
</project>
|
||||
85
spring-ldap-odm/build.xml
Normal file
85
spring-ldap-odm/build.xml
Normal file
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<project name="spring-ldap-odm" default="dist">
|
||||
|
||||
<property file="build.properties" />
|
||||
<property file="project.properties" />
|
||||
<property file="${common.build.dir}/build.properties" />
|
||||
<property file="${common.build.dir}/project.properties" />
|
||||
<property file="${user.home}/build.properties" />
|
||||
|
||||
<property name="project.title" value="Spring LDAP ODM" />
|
||||
<property name="project.package" value="org.springframework.ldap.odm" />
|
||||
|
||||
<property name="ldap.server" value="127.0.0.1" />
|
||||
<property name="ldap.user" value=""cn=Manager,dc=jayway,dc=se"" />
|
||||
<property name="ldap.password" value="secret" />
|
||||
|
||||
<!-- Cannot import common-targets since itest-targets already does -->
|
||||
<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" />
|
||||
|
||||
<!-- extend common-build with source capability -->
|
||||
<target name="build.prepare.make.config.dirs" depends="common-targets.build.prepare.make.config.dirs">
|
||||
<mkdir dir="${lib.dir}/source" />
|
||||
</target>
|
||||
|
||||
<!--
|
||||
Overridden to create test report and run integration tests as well.
|
||||
-->
|
||||
<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.
|
||||
-->
|
||||
<!-- Runs the local unit tests. -->
|
||||
<target name="tests-local" depends="tests.prepare" description="Run all local tests">
|
||||
<!-- for the time being we just halt on failure, since these are
|
||||
local tests and there is no server to shut down, etc. But if
|
||||
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">
|
||||
<jvmarg value="${unitvm}" />
|
||||
<jvmarg value="-Djava.security.auth.login.config=${target.testclasses.dir}/auth.conf" />
|
||||
<jvmarg value="${test.arguments}" />
|
||||
<classpath>
|
||||
<pathelement location="${target.classes.dir}" />
|
||||
<pathelement location="${target.testclasses.dir}" />
|
||||
<pathelement location="${target.genclasses.dir}" />
|
||||
<path refid="test.classpath" />
|
||||
</classpath>
|
||||
|
||||
<formatter type="plain" />
|
||||
<formatter type="xml" />
|
||||
|
||||
<batchtest fork="yes" todir="${target.testresults.dir}">
|
||||
<fileset dir="${target.testclasses.dir}" includes="${test.includes}" excludes="${test.excludes}" />
|
||||
</batchtest>
|
||||
</junit>
|
||||
|
||||
</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}" />
|
||||
<mkdir dir="${target.testresults.html.dir}" />
|
||||
<junitreport todir="${target.testresults.html.dir}">
|
||||
<fileset dir="${target.testresults.dir}">
|
||||
<include name="TEST-*.xml" />
|
||||
</fileset>
|
||||
<report format="frames" todir="${target.testresults.html.dir}" />
|
||||
</junitreport>
|
||||
<echo>
|
||||
Unit test report has been generated.
|
||||
The HTML report is ${target.testresults.html.dir}/index.html
|
||||
</echo>
|
||||
<fail if="tests.failed" message="Unit tests failed" />
|
||||
</target>
|
||||
|
||||
</project>
|
||||
95
spring-ldap-odm/ivy.xml
Normal file
95
spring-ldap-odm/ivy.xml
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ivy-module version="1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://www.jayasoft.org/misc/ivy/samples/ivy.xsd">
|
||||
|
||||
<info organisation="org.springframework" module="spring-ldap-odm" />
|
||||
|
||||
<configurations>
|
||||
<conf name="default" extends="global" />
|
||||
<conf name="global" visibility="private" />
|
||||
<conf name="buildtime" visibility="private" />
|
||||
<conf name="test" visibility="private" />
|
||||
<conf name="source" visibility="public" />
|
||||
</configurations>
|
||||
|
||||
<publications>
|
||||
<artifact name="spring-ldap-odm" type="jar" conf="default" />
|
||||
<artifact name="spring-ldap-odm-src" type="zip" conf="source" />
|
||||
</publications>
|
||||
|
||||
<dependencies defaultconf="global->default">
|
||||
<!-- global (core) dependencies -->
|
||||
<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-beans" rev="2.0.2"/>
|
||||
<dependency org="org.springframework" name="spring-core" rev="2.0.2"/>
|
||||
<dependency org="org.springframework" name="spring-context" rev="2.0.2"/>
|
||||
<dependency org="org.springframework" name="spring-dao" rev="2.0.2"/>
|
||||
<dependency org="org.springframework" name="spring-src" rev="2.0.2" conf="source->source">
|
||||
<artifact name="spring-src" type="zip"/>
|
||||
</dependency>
|
||||
<dependency org="com.sun" name="ldapbp" rev="1.0" />
|
||||
<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>
|
||||
|
||||
<!-- test time only dependencies -->
|
||||
<dependency org="com.cenqua.clover" name="clover" rev="1.3.12" conf="test->default" />
|
||||
<dependency org="org.springframework" name="spring-mock" rev="2.0.2"
|
||||
conf="test->default"/>
|
||||
<dependency org="gsbase" name="gsbase" rev="2.0.1" conf="test->default"/>
|
||||
<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" />
|
||||
|
||||
<!-- Test dependencies for Apache Directory Server -->
|
||||
<dependency org="org.apache.directory.server" name="apacheds-core" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<dependency org="org.apache.directory.server" name="apacheds-core-shared" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<dependency org="org.apache.directory.server" name="apacheds-server-jndi" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<dependency org="org.apache.directory.server" name="apacheds-server-main" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<dependency org="org.apache.directory.server" name="apacheds-protocol-shared" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<dependency org="org.apache.directory.server" name="apacheds-protocol-changepw" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<dependency org="org.apache.directory.server" name="apacheds-protocol-kerberos" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<dependency org="org.apache.directory.server" name="apacheds-kerberos-shared" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<dependency org="org.apache.directory.server" name="apacheds-protocol-ldap" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
|
||||
<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-ldap" rev="0.9.5.3"
|
||||
conf="test->default"/>
|
||||
|
||||
<dependency org="log4j" name="log4j" rev="1.2.9" conf="test->default" />
|
||||
<dependency org="antlr" name="antlr" rev="2.7.2" conf="test->default" />
|
||||
<dependency org="jdbm" name="jdbm" rev="1.0" conf="test->default" />
|
||||
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.0"
|
||||
conf="test->default" />
|
||||
<dependency org="org.apache.mina" name="mina-core" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<dependency org="org.apache.mina" name="mina-filter-ssl" rev="1.0.0"
|
||||
conf="test->default"/>
|
||||
<!-- End test dependencies for Apache Directory Server -->
|
||||
|
||||
</dependencies>
|
||||
|
||||
</ivy-module>
|
||||
14
spring-ldap-odm/project.properties
Normal file
14
spring-ldap-odm/project.properties
Normal file
@@ -0,0 +1,14 @@
|
||||
# properties defined in this file are overridable by a local build.properties in this project dir
|
||||
|
||||
# The location of the common build system
|
||||
common.build.dir=${basedir}/../common-build
|
||||
|
||||
project.base.version=1.2-dev
|
||||
#project.version=${project.base.version}
|
||||
#ivy.status=release
|
||||
|
||||
javac.source=1.5
|
||||
javac.target=1.5
|
||||
|
||||
# extend common-build with source capability
|
||||
main.build.configs=global,buildtime,test,source
|
||||
34
spring-ldap-odm/src/itest/java/conf/beans.xml
Normal file
34
spring-ldap-odm/src/itest/java/conf/beans.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!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>
|
||||
|
||||
<bean id="ldapTemplate" singleton="true" class="org.springframework.ldap.core.LdapTemplate">
|
||||
<constructor-arg ref="contextSource"/>
|
||||
</bean>
|
||||
|
||||
<bean id="typeConverter" singleton="true" class="org.springframework.ldap.odm.attributetypes.LdapTypeConverter"/>
|
||||
|
||||
<bean id="referencedEntryEditorFactory" singleton="true"
|
||||
class="org.springframework.ldap.odm.attributetypes.ReferencedEntryEditorFactory">
|
||||
<constructor-arg ref="ldapTemplate"/>
|
||||
</bean>
|
||||
|
||||
<bean id="ctxMapperFactory" singleton="true"
|
||||
class="org.springframework.ldap.odm.contextmapping.ContextMapperFactory">
|
||||
<constructor-arg ref="typeConverter"/>
|
||||
<constructor-arg ref="referencedEntryEditorFactory"/>
|
||||
</bean>
|
||||
|
||||
<bean id="ldapDao" singleton="true" class="org.springframework.ldap.odm.dao.LdapDaoImpl">
|
||||
<constructor-arg ref="ldapTemplate"/>
|
||||
<constructor-arg ref="ctxMapperFactory"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* 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 java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
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.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 org.testng.annotations.Test;
|
||||
|
||||
public class AnnotatedClassContextMapperTest extends
|
||||
AbstractDependencyInjectionSpringContextTests {
|
||||
private static final Log LOGGER = LogFactory
|
||||
.getLog(AnnotatedClassContextMapperTest.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 {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
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 {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
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 {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
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 {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
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 {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
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 {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
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");
|
||||
|
||||
}
|
||||
|
||||
@Test(groups = { "AnnotatedClassContextMapper" }, expectedExceptions = ContextMapperException.class)
|
||||
public void throwsExceptionWhenNamingSuffixHasSyntaxError()
|
||||
throws ContextMapperException {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
MockModelNamingSuffixSyntaxError.class, typeConverter,
|
||||
refEditorFactory);
|
||||
Assert
|
||||
.fail("AnnotatedClassContextMapper should throw an exception when naming path annotation syntax is "
|
||||
+ "incorrect.");
|
||||
}
|
||||
|
||||
@Test(groups = { "AnnotatedClassContextMapper" }, expectedExceptions = ContextMapperException.class)
|
||||
public void throwsExceptionWhenNamingSuffixNotInSeparateElements()
|
||||
throws ContextMapperException {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
MockModelNamingSuffixNotInSeparateElements.class,
|
||||
typeConverter, refEditorFactory);
|
||||
Assert
|
||||
.fail("AnnotatedClassContextMapper should throw an exception when naming path annotation syntax is "
|
||||
+ "incorrect.");
|
||||
}
|
||||
|
||||
@Test(groups = { "AnnotatedClassContextMapper" }, expectedExceptions = ContextMapperException.class)
|
||||
public void throwsExceptionWhenModelObjectMissingGetterOrSetter()
|
||||
throws ContextMapperException {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
MockModelMissingSetter.class, typeConverter, refEditorFactory);
|
||||
Assert.fail("Should've thrown exception due to missing getter/setter");
|
||||
}
|
||||
|
||||
@Test(groups = { "AnnotatedClassContextMapper" })
|
||||
public void throwsExceptionWhenBeanPropertyNotAValidTranslationType() {
|
||||
try {
|
||||
AnnotatedClassContextMapper contextMapper = new AnnotatedClassContextMapper(
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* 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.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.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;
|
||||
|
||||
|
||||
public class LdapDaoTest
|
||||
{
|
||||
|
||||
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()
|
||||
{
|
||||
LOGGER.debug("********************INIT TEST CLASS**************************");
|
||||
|
||||
applicationContext = new ClassPathXmlApplicationContext("beans.xml");
|
||||
ldapDao = (LdapDao) applicationContext.getBean("ldapDao");
|
||||
}
|
||||
|
||||
@BeforeMethod(alwaysRun = true)
|
||||
public void createPerMethodConsumer()
|
||||
{
|
||||
LOGGER.debug("********************CREATE PER METHOD CONSUMER**************************");
|
||||
testPerson = new TestPerson();
|
||||
testPerson.setIdentifier("fred" + System.currentTimeMillis());
|
||||
testPerson.setEmailAddress("fred@fred.com");
|
||||
testPerson.setFullName("Fred (Freddy) Fredrickson");
|
||||
testPerson.setLastName("Fredrickson");
|
||||
testPerson.setGivenName("Fred");
|
||||
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()
|
||||
{
|
||||
try
|
||||
{
|
||||
ldapDao.create(testPerson);
|
||||
}
|
||||
catch (Exception unexpected)
|
||||
{
|
||||
Assert.fail("Creating a new user failed: " + unexpected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void createOrUpdateEntity()
|
||||
{
|
||||
try
|
||||
{
|
||||
ldapDao.create(testPerson);
|
||||
ldapDao.createOrUpdate(testPerson);
|
||||
}
|
||||
catch (Exception unexpected)
|
||||
{
|
||||
Assert.fail("Creating a new user failed: " + unexpected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void findByNamingAttribute()
|
||||
{
|
||||
ldapDao.create(testPerson);
|
||||
TestPerson retrieved = (TestPerson) ldapDao.findByNamingAttribute(testPerson.getIdentifier(), TestPerson.class);
|
||||
LOGGER.debug(retrieved);
|
||||
Assert.assertNotNull(retrieved, "Should've found the created entity.");
|
||||
}
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void findRoles()
|
||||
{
|
||||
ldapDao.create(testPerson);
|
||||
validRole.setMembers(new TestPerson[]{testPerson});
|
||||
ldapDao.createOrUpdate(validRole);
|
||||
TestRole role = (TestRole) ldapDao.findByNamingAttribute("webUser", TestRole.class);
|
||||
LOGGER.debug(role);
|
||||
}
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void findByDn()
|
||||
{
|
||||
ldapDao.create(testPerson);
|
||||
DistinguishedName dn = new DistinguishedName("uid=" + testPerson.getIdentifier() + ",ou=people");
|
||||
TestPerson retrieved = (TestPerson) ldapDao.findByDn(dn, TestPerson.class);
|
||||
LOGGER.debug(retrieved);
|
||||
Assert.assertNotNull(retrieved, "Should've found the created entity.");
|
||||
}
|
||||
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void createEntityThrowsExceptionWhenNameAlreadyBound()
|
||||
{
|
||||
try
|
||||
{
|
||||
ldapDao.create(testPerson);
|
||||
ldapDao.create(testPerson);
|
||||
Assert.fail("Should throw DaoException when name already bound.");
|
||||
}
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void findAll()
|
||||
{
|
||||
List results = ldapDao.findAll(TestPerson.class);
|
||||
Assert.assertTrue(results.size() > 0);
|
||||
}
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void filterByBeanProperty()
|
||||
{
|
||||
ldapDao.create(testPerson);
|
||||
List results = ldapDao.filterByBeanProperty(testPerson.getEmailAddress(), "EmailAddress", TestPerson.class);
|
||||
LOGGER.debug("filterByBeanProperty returned: " + results.size() + " results.");
|
||||
Assert.assertTrue(results.size() > 0, "Filter should return collection containing more than one result. ");
|
||||
}
|
||||
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void updateEntity()
|
||||
{
|
||||
try
|
||||
{
|
||||
ldapDao.create(testPerson);
|
||||
String newEmail = "new@email.com";
|
||||
testPerson.setEmailAddress(newEmail);
|
||||
ldapDao.update(testPerson);
|
||||
TestPerson retrieved = (TestPerson) ldapDao.findByNamingAttribute(testPerson.getIdentifier(),
|
||||
TestPerson.class);
|
||||
Assert.assertEquals(retrieved.getEmailAddress(), newEmail, "Email name not updated.");
|
||||
}
|
||||
catch (Exception unexpected)
|
||||
{
|
||||
Assert.fail("Unable to update the details of an existing user: " + unexpected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void updateEntityThrowsExceptionWhenNameNotBound()
|
||||
{
|
||||
try
|
||||
{
|
||||
String newEmail = "new@email.com";
|
||||
testPerson.setEmailAddress(newEmail);
|
||||
ldapDao.update(testPerson);
|
||||
Assert.fail("Should've failed since the entry doesn't exist");
|
||||
}
|
||||
catch (EntryNotFoundException e)
|
||||
{
|
||||
Assert.assertTrue(e instanceof EntryNotFoundException);
|
||||
Assert.assertTrue(e.getMessage().contains("Entry not found"), "Error message not as expected.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = "LdapDao")
|
||||
public void deleteEntity()
|
||||
{
|
||||
ldapDao.create(testPerson);
|
||||
LOGGER.debug(testPerson);
|
||||
ldapDao.delete(testPerson);
|
||||
TestPerson retrieved = (TestPerson) ldapDao.findByNamingAttribute(testPerson.getIdentifier(), TestPerson.class);
|
||||
Assert.assertNull(retrieved, "Entity should've been deleted.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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.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;
|
||||
|
||||
@NamingAttribute("cn")
|
||||
@NamingSuffix({"ou = people", "dc = example", "dc=com"})
|
||||
@ObjectClasses({"top", "person", "organizationalPerson", "inetorgperson"})
|
||||
public class MockEntity
|
||||
{
|
||||
|
||||
@DirAttribute("cn")
|
||||
private String name;
|
||||
|
||||
@DirAttribute("addr")
|
||||
private String address;
|
||||
|
||||
@DirAttribute("mail")
|
||||
private String mail;
|
||||
|
||||
@DirAttribute("userpassword")
|
||||
private byte[] password;
|
||||
|
||||
@DirAttribute("desc")
|
||||
private String[] description;
|
||||
|
||||
@DirAttribute("acceptemails")
|
||||
private Boolean acceptEmails;
|
||||
|
||||
@DirAttribute("loginresettime")
|
||||
private Date resetLogin;
|
||||
|
||||
@DirAttribute("failedlogins")
|
||||
private Integer failedLogins;
|
||||
|
||||
@DirAttribute("creatorname")
|
||||
private DistinguishedName creator;
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getAddress()
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address)
|
||||
{
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getMail()
|
||||
{
|
||||
return mail;
|
||||
}
|
||||
|
||||
public void setMail(String mail)
|
||||
{
|
||||
this.mail = mail;
|
||||
}
|
||||
|
||||
public byte[] getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(byte[] password)
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String[] getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String[] description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Boolean getAcceptEmails()
|
||||
{
|
||||
return acceptEmails;
|
||||
}
|
||||
|
||||
public void setAcceptEmails(Boolean acceptEmails)
|
||||
{
|
||||
this.acceptEmails = acceptEmails;
|
||||
}
|
||||
|
||||
public Date getResetLogin()
|
||||
{
|
||||
return resetLogin;
|
||||
}
|
||||
|
||||
public void setResetLogin(Date resetLogin)
|
||||
{
|
||||
this.resetLogin = resetLogin;
|
||||
}
|
||||
|
||||
public Integer getFailedLogins()
|
||||
{
|
||||
return failedLogins;
|
||||
}
|
||||
|
||||
public void setFailedLogins(Integer failedLogins)
|
||||
{
|
||||
this.failedLogins = failedLogins;
|
||||
}
|
||||
|
||||
public DistinguishedName getCreator()
|
||||
{
|
||||
return creator;
|
||||
}
|
||||
|
||||
public void setCreator(DistinguishedName creator)
|
||||
{
|
||||
this.creator = creator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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.entity;
|
||||
|
||||
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 com.thoughtworks.xstream.XStream;
|
||||
|
||||
|
||||
@NamingAttribute("uid")
|
||||
@NamingSuffix({"ou=people"})
|
||||
@ObjectClasses({"top", "person", "organizationalPerson", "inetorgperson"})
|
||||
public class TestPerson
|
||||
{
|
||||
/*********************************** Directory mapped fields ************************************/
|
||||
@DirAttribute("uid")
|
||||
private String identifier;
|
||||
|
||||
@DirAttribute("sn")
|
||||
private String lastName;
|
||||
|
||||
@DirAttribute("givenName")
|
||||
private String givenName;
|
||||
|
||||
@DirAttribute("cn")
|
||||
private String fullName;
|
||||
|
||||
@DirAttribute("mail")
|
||||
private String emailAddress;
|
||||
|
||||
@DirAttribute("userpassword")
|
||||
private byte[] password;
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
public String getIdentifier()
|
||||
{
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(String identifier)
|
||||
{
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getLastName()
|
||||
{
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName)
|
||||
{
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getGivenName()
|
||||
{
|
||||
return givenName;
|
||||
}
|
||||
|
||||
public void setGivenName(String givenName)
|
||||
{
|
||||
this.givenName = givenName;
|
||||
}
|
||||
|
||||
public String getFullName()
|
||||
{
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public void setFullName(String fullName)
|
||||
{
|
||||
this.fullName = fullName;
|
||||
}
|
||||
|
||||
public String getEmailAddress()
|
||||
{
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
public void setEmailAddress(String emailAddress)
|
||||
{
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
public byte[] getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(byte[] password)
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
XStream xStream = new XStream();
|
||||
xStream.alias("TestPerson", TestPerson.class);
|
||||
return "\n" + xStream.toXML(this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.entity;
|
||||
|
||||
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 com.thoughtworks.xstream.XStream;
|
||||
|
||||
@NamingAttribute("cn")
|
||||
@NamingSuffix({"ou=roles"})
|
||||
@ObjectClasses({"top", "organizationalRole"})
|
||||
|
||||
public class TestRole
|
||||
{
|
||||
/*********************************** Directory mapped fields ************************************/
|
||||
@DirAttribute("cn")
|
||||
private String roleName;
|
||||
|
||||
@DirAttribute
|
||||
private String description;
|
||||
|
||||
@DirAttribute("roleOccupant")
|
||||
private TestPerson[] members;
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
public String getRoleName()
|
||||
{
|
||||
return roleName;
|
||||
}
|
||||
|
||||
public void setRoleName(String roleName)
|
||||
{
|
||||
this.roleName = roleName;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public TestPerson[] getMembers()
|
||||
{
|
||||
return members;
|
||||
}
|
||||
|
||||
public void setMembers(TestPerson[] members)
|
||||
{
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
XStream xStream = new XStream();
|
||||
xStream.alias("TestRole", TestRole.class);
|
||||
xStream.alias("TestPerson", TestPerson.class);
|
||||
return "\n" + xStream.toXML(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import java.lang.annotation.Retention;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Documented
|
||||
@Target({FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface DirAttribute
|
||||
{
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import java.lang.annotation.Retention;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface NamingAttribute
|
||||
{
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import java.lang.annotation.Retention;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Target;
|
||||
/*
|
||||
* Copyright 2006 by Sensis. All Rights Reserved.
|
||||
*
|
||||
* This software is the proprietary information of Majitek. Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface NamingSuffix
|
||||
{
|
||||
String[] value();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import java.lang.annotation.Retention;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ObjectClasses
|
||||
{
|
||||
String[] value();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.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;
|
||||
|
||||
public class LdapTypeConverter extends SimpleTypeConverter
|
||||
{
|
||||
|
||||
public LdapTypeConverter()
|
||||
{
|
||||
super();
|
||||
registerCustomEditor(Date.class,
|
||||
new CustomDateEditor(new SimpleDateFormat("yyyyMMddHHmmss.S"), true));
|
||||
registerCustomEditor(LdapName.class, new NameEditor(LdapName.class));
|
||||
registerCustomEditor(DistinguishedName.class, new NameEditor(DistinguishedName.class));
|
||||
}
|
||||
|
||||
public String getAsText(Object value)
|
||||
{
|
||||
if (value instanceof String)
|
||||
{
|
||||
return (String) value;
|
||||
}
|
||||
PropertyEditor pe = propertyEditorFor(value.getClass());
|
||||
if (pe != null)
|
||||
{
|
||||
pe.setValue(value);
|
||||
return pe.getAsText();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getAllAsText(Object[] values)
|
||||
{
|
||||
String[] textValues = new String[values.length];
|
||||
for (int i = 0; i < values.length; i++)
|
||||
{
|
||||
textValues[i] = getAsText(values[i]);
|
||||
}
|
||||
return textValues;
|
||||
}
|
||||
|
||||
private PropertyEditor propertyEditorFor(Class clazz)
|
||||
{
|
||||
PropertyEditor pe = findCustomEditor(clazz, null);
|
||||
if (pe != null)
|
||||
{
|
||||
return pe;
|
||||
}
|
||||
else
|
||||
{
|
||||
pe = getDefaultEditor(clazz);
|
||||
return pe;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.attributetypes;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
import javax.naming.ldap.LdapName;
|
||||
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
|
||||
public class NameEditor extends PropertyEditorSupport
|
||||
{
|
||||
private Class conversionClass;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
public String getAsText()
|
||||
{
|
||||
Object value = conversionClass.cast(getValue());
|
||||
return value != null ? value.toString() : "";
|
||||
}
|
||||
|
||||
public void setAsText(String text) throws IllegalArgumentException
|
||||
{
|
||||
try
|
||||
{
|
||||
setValue(conversionClass.getConstructor(String.class).newInstance(text));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.attributetypes;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
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;
|
||||
|
||||
public class ReferencedEntryEditor extends PropertyEditorSupport
|
||||
{
|
||||
private LdapTemplate ldapTemplate;
|
||||
private AnnotatedClassContextMapper contextMapper;
|
||||
|
||||
public ReferencedEntryEditor(LdapTemplate ldapTemplate, AnnotatedClassContextMapper contextMapper)
|
||||
{
|
||||
this.ldapTemplate = ldapTemplate;
|
||||
this.contextMapper = contextMapper;
|
||||
}
|
||||
|
||||
public String getAsText()
|
||||
{
|
||||
try
|
||||
{
|
||||
return contextMapper.buildDn(getValue()).toString();
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
throw new RuntimeException("No context mapper for class: " + getValue().getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
public void setAsText(String text) throws IllegalArgumentException
|
||||
{
|
||||
try
|
||||
{
|
||||
setValue(ldapTemplate.lookup(new LdapName(text), contextMapper));
|
||||
}
|
||||
catch (InvalidNameException e)
|
||||
{
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.attributetypes;
|
||||
|
||||
import java.util.HashMap;
|
||||
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.exception.ContextMapperException;
|
||||
|
||||
public class ReferencedEntryEditorFactory
|
||||
{
|
||||
private static final Log LOGGER = LogFactory.getLog(ReferencedEntryEditorFactory.class);
|
||||
private ContextMapperFactory contextMapperFactory;
|
||||
private LdapTemplate ldapTemplate;
|
||||
private Map<Class, ReferencedEntryEditor> referencedEntryEditors;
|
||||
|
||||
public ReferencedEntryEditorFactory(
|
||||
LdapTemplate ldapTemplate)
|
||||
{
|
||||
this.ldapTemplate = ldapTemplate;
|
||||
this.referencedEntryEditors = new HashMap();
|
||||
}
|
||||
|
||||
public ReferencedEntryEditor referencedEntryEditorForClass(Class clazz)
|
||||
throws ReferencedEntryEditorCreationException
|
||||
{
|
||||
if (referencedEntryEditors.containsKey(clazz))
|
||||
{
|
||||
LOGGER.debug("Returning cached referenced entry editor for class: " + clazz.getSimpleName());
|
||||
return referencedEntryEditors.get(clazz);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.debug("Attempting to create a referenced entry editor for class: "
|
||||
+ clazz.getSimpleName());
|
||||
AnnotatedClassContextMapper contextMapper = null;
|
||||
try
|
||||
{
|
||||
contextMapper = contextMapperFactory.contextMapperForClass(clazz);
|
||||
ReferencedEntryEditor referencedEntryEditor =
|
||||
new ReferencedEntryEditor(ldapTemplate, contextMapper);
|
||||
referencedEntryEditors.put(clazz, referencedEntryEditor);
|
||||
return referencedEntryEditor;
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
throw new ReferencedEntryEditorCreationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setContextMapperFactory(ContextMapperFactory contextMapperFactory)
|
||||
{
|
||||
this.contextMapperFactory = contextMapperFactory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.attributetypes;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.naming.ldap.LdapName;
|
||||
|
||||
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
|
||||
{
|
||||
BYTE_ARRAY(byte[].class),
|
||||
BOOLEAN(Boolean.class),
|
||||
STRING(String.class),
|
||||
STRING_ARRAY(String[].class),
|
||||
DATE(Date.class),
|
||||
DATE_ARRAY(Date[].class),
|
||||
LDAP_NAME(LdapName.class),
|
||||
LDAP_NAME_ARRAY(LdapName[].class),
|
||||
DISTINGUISHED_NAME(DistinguishedName.class),
|
||||
DISTINGUISHED_NAME_ARRAY(DistinguishedName[].class),
|
||||
INTEGER(Integer.class),
|
||||
INTEGER_ARRAY(Integer[].class),
|
||||
LONG(Long.class),
|
||||
LONG_ARRAY(Long[].class);
|
||||
|
||||
private final Class clazz;
|
||||
|
||||
|
||||
ValidConversionType(Class validType)
|
||||
{
|
||||
this.clazz = validType;
|
||||
|
||||
}
|
||||
|
||||
public Class getClazz()
|
||||
{
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public static String listTypes()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < ValidConversionType.values().length; i++)
|
||||
{
|
||||
ValidConversionType validType = ValidConversionType.values()[i];
|
||||
sb.append("\n");
|
||||
sb.append(validType.getClazz().getSimpleName());
|
||||
if (i != ValidConversionType.values().length - 1)
|
||||
{
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static boolean isValidConversionType(Class returnType)
|
||||
{
|
||||
for (ValidConversionType type : ValidConversionType.values())
|
||||
{
|
||||
if (returnType.equals(type.getClazz()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* 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.attributetypes.exception;
|
||||
|
||||
public class ReferencedEntryEditorCreationException extends Exception
|
||||
{
|
||||
public ReferencedEntryEditorCreationException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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 java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.Name;
|
||||
import javax.naming.directory.Attribute;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.ldap.core.ContextAssembler;
|
||||
import org.springframework.ldap.core.ContextMapper;
|
||||
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.attributetypes.ValidConversionType;
|
||||
import org.springframework.ldap.odm.attributetypes.exception.ReferencedEntryEditorCreationException;
|
||||
import org.springframework.ldap.odm.contextmapping.exception.ContextMapperException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class AnnotatedClassContextMapper implements ContextMapper, ContextAssembler
|
||||
{
|
||||
private static final Log LOGGER = LogFactory.getLog(AnnotatedClassContextMapper.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 AnnotatedClassContextMapper(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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
|
||||
public class AttributeDecorator
|
||||
{
|
||||
private Attribute attribute;
|
||||
|
||||
public AttributeDecorator(Attribute attribute)
|
||||
{
|
||||
this.attribute = attribute;
|
||||
}
|
||||
|
||||
public Object getAllAsObject() throws NamingException
|
||||
{
|
||||
if (attribute != null)
|
||||
{
|
||||
if (attribute.size() == 1)
|
||||
{
|
||||
return attribute.get(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Object[] o = new Object[attribute.size()];
|
||||
for (int i = 0; i < attribute.size(); i++)
|
||||
{
|
||||
o[i] = attribute.get(i);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/** A bi-directional map of bean property names to attribute names */
|
||||
public class ContextMap
|
||||
{
|
||||
private static final Log LOGGER = LogFactory.getLog(ContextMap.class);
|
||||
private Map<String, String> beanPropertyNameKeys;
|
||||
private Map<String, String> attributeNameKeys;
|
||||
|
||||
public ContextMap()
|
||||
{
|
||||
beanPropertyNameKeys = new HashMap();
|
||||
attributeNameKeys = new HashMap();
|
||||
}
|
||||
|
||||
public void map(String beanPropertyName, String toAttributeName)
|
||||
{
|
||||
LOGGER.info("Bean property '" + beanPropertyName + "' maps to ldap attribute '" + toAttributeName + "'");
|
||||
beanPropertyNameKeys.put(beanPropertyName, toAttributeName);
|
||||
attributeNameKeys.put(toAttributeName, beanPropertyName);
|
||||
}
|
||||
|
||||
public String beanPropertyNameFor(String attributeName)
|
||||
{
|
||||
return attributeNameKeys.get(attributeName);
|
||||
}
|
||||
|
||||
public String attributeNameFor(String beanPropertyName)
|
||||
{
|
||||
return beanPropertyNameKeys.get(beanPropertyName);
|
||||
}
|
||||
|
||||
public Set<String> beanPropertyNames()
|
||||
{
|
||||
return beanPropertyNameKeys.keySet();
|
||||
}
|
||||
|
||||
public Set<String> attributeNames()
|
||||
{
|
||||
return attributeNameKeys.keySet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.odm.attributetypes.LdapTypeConverter;
|
||||
import org.springframework.ldap.odm.attributetypes.ReferencedEntryEditorFactory;
|
||||
import org.springframework.ldap.odm.contextmapping.exception.ContextMapperException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ContextMapperFactory
|
||||
{
|
||||
private static final Log LOGGER = LogFactory.getLog(ContextMapperFactory.class);
|
||||
private Map<Class, AnnotatedClassContextMapper> contextMappers;
|
||||
private LdapTypeConverter typeConverter;
|
||||
private ReferencedEntryEditorFactory referencedEntryEditorFactory;
|
||||
|
||||
public ContextMapperFactory(LdapTypeConverter typeConverter,
|
||||
ReferencedEntryEditorFactory referencedEntryEditorFactory)
|
||||
{
|
||||
contextMappers = new HashMap<Class, AnnotatedClassContextMapper>();
|
||||
this.typeConverter = typeConverter;
|
||||
this.referencedEntryEditorFactory = referencedEntryEditorFactory;
|
||||
this.referencedEntryEditorFactory.setContextMapperFactory(this);
|
||||
}
|
||||
|
||||
public AnnotatedClassContextMapper contextMapperForClass(Class clazz)
|
||||
throws ContextMapperException
|
||||
{
|
||||
if (contextMappers.containsKey(clazz))
|
||||
{
|
||||
LOGGER.debug("Returning cached context mapper for class: " + clazz.getSimpleName());
|
||||
return contextMappers.get(clazz);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.debug("Attempting to create a context mapper for class: " + clazz.getSimpleName());
|
||||
AnnotatedClassContextMapper contextMapper =
|
||||
new AnnotatedClassContextMapper(clazz, typeConverter, referencedEntryEditorFactory);
|
||||
contextMappers.put(clazz, contextMapper);
|
||||
return contextMapper;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
public class ContextMapperException extends Exception
|
||||
{
|
||||
|
||||
|
||||
public ContextMapperException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ContextMapperException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.Name;
|
||||
|
||||
public interface LdapDao
|
||||
{
|
||||
void create(Object dirObject);
|
||||
|
||||
void update(Object dirObject);
|
||||
|
||||
void createOrUpdate(Object dirObject);
|
||||
|
||||
void delete(Object dirObject);
|
||||
|
||||
Object findByNamingAttribute(String namingValue, Class returnType);
|
||||
|
||||
public Object findByDn(Name dn, Class returnType);
|
||||
|
||||
List findAll(Class ofType);
|
||||
|
||||
List filterByBeanProperty(String value, String beanPropertyName, Class returnType);
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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.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.odm.contextmapping.ContextMapperFactory;
|
||||
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;
|
||||
|
||||
public class LdapDaoImpl implements LdapDao
|
||||
{
|
||||
static final Log LOGGER = LogFactory.getLog(LdapDaoImpl.class);
|
||||
LdapTemplate ldapTemplate;
|
||||
ContextMapperFactory ctxMapperFactory;
|
||||
|
||||
public LdapDaoImpl(LdapTemplate ldapTemplate, ContextMapperFactory ctxMapperFactory)
|
||||
{
|
||||
this.ldapTemplate = ldapTemplate;
|
||||
this.ctxMapperFactory = ctxMapperFactory;
|
||||
}
|
||||
|
||||
public void create(Object dirObject)
|
||||
{
|
||||
DirContextAdapter context = new DirContextAdapter();
|
||||
try
|
||||
{
|
||||
AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
|
||||
ctxMapper.mapToContext(dirObject, context);
|
||||
ldapTemplate.bind(ctxMapper.buildDn(dirObject), context, null);
|
||||
}
|
||||
catch (org.springframework.dao.DataIntegrityViolationException dive)
|
||||
{
|
||||
throw new DataIntegrityViolationException(dive.getMessage());
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
throw new DaoException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Object dirObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
AnnotatedClassContextMapper 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);
|
||||
}
|
||||
}
|
||||
|
||||
public void createOrUpdate(Object dirObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
|
||||
if (findByDn(ctxMapper.buildDn(dirObject), dirObject.getClass()) == null)
|
||||
{
|
||||
create(dirObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
update(dirObject);
|
||||
}
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
throw new DaoException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void delete(Object dirObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
|
||||
ldapTemplate.unbind(ctxMapper.buildDn(dirObject));
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new DaoException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public Object findByNamingAttribute(String namingAttributeValue, Class returnType)
|
||||
{
|
||||
try
|
||||
{
|
||||
AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(returnType);
|
||||
Name dn = ctxMapper.buildDn(namingAttributeValue);
|
||||
return findByDn(dn, returnType);
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
throw new DaoException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public Object findByDn(Name dn, Class returnType)
|
||||
{
|
||||
try
|
||||
{
|
||||
AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(returnType);
|
||||
return ldapTemplate.lookup(dn, ctxMapper);
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
throw new DaoException(e.getMessage(), e);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List filterByBeanProperty(String value, String beanPropertyName, Class returnType)
|
||||
{
|
||||
try
|
||||
{
|
||||
LOGGER.debug("Filtering on property: " + beanPropertyName + ", for value: " + value);
|
||||
AnnotatedClassContextMapper ctxMapper =
|
||||
ctxMapperFactory.contextMapperForClass(returnType);
|
||||
|
||||
try
|
||||
{
|
||||
String attributeName = ctxMapper.getContextMap().attributeNameFor(beanPropertyName);
|
||||
String filter = attributeName + "=" + value;
|
||||
List results = ldapTemplate.search(ctxMapper.getNamingSuffix().toString(), filter,
|
||||
ctxMapperFactory.contextMapperForClass(returnType));
|
||||
LOGGER.debug(results.size() + " results found for filter: " + filter);
|
||||
return results;
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
throw new DaoException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
throw new DaoException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public List findAll(Class ofType)
|
||||
{
|
||||
try
|
||||
{
|
||||
AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(ofType);
|
||||
StringBuilder filterBuilder = new StringBuilder();
|
||||
filterBuilder.append("(&");
|
||||
for (String objectClass : ctxMapper.getObjectClasses())
|
||||
{
|
||||
filterBuilder.append("(objectClass=");
|
||||
filterBuilder.append(objectClass);
|
||||
filterBuilder.append(")");
|
||||
}
|
||||
filterBuilder.append(")");
|
||||
List results = ldapTemplate.search(DistinguishedName.EMPTY_PATH, filterBuilder.toString(), ctxMapper);
|
||||
LOGGER.debug("Found " + results.size() + " entries of type " + ofType.getSimpleName());
|
||||
return results;
|
||||
}
|
||||
catch (ContextMapperException e)
|
||||
{
|
||||
throw new DaoException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.dao.exception;
|
||||
|
||||
public class DaoException extends RuntimeException
|
||||
{
|
||||
public DaoException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DaoException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.dao.exception;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A Serializable version of org.springframework.dao.DataIntegrityViolationException
|
||||
*/
|
||||
public class DataIntegrityViolationException extends DaoException
|
||||
{
|
||||
|
||||
private List<String> nonUniqueAttributes;
|
||||
|
||||
public DataIntegrityViolationException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DataIntegrityViolationException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.dao.exception;
|
||||
|
||||
/**
|
||||
* A Serializable version of org.springframework.dao.EntryNotFoundException
|
||||
*/
|
||||
public class EntryNotFoundException extends DaoException
|
||||
{
|
||||
|
||||
public EntryNotFoundException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* 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.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);
|
||||
|
||||
private LdapTypeConverter typeConverter;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
typeConverter = new LdapTypeConverter();
|
||||
}
|
||||
|
||||
public void testConvertToByteArray() {
|
||||
byte[] objectToTranslate = "fred".getBytes();
|
||||
|
||||
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 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 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 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 testConvertToStringArray() {
|
||||
String object1 = "onetwothree";
|
||||
String object2 = "fourfivesix";
|
||||
String object3 = "seveneightnine";
|
||||
Object objectToTranslate = new String[] { object1, object2, object3 };
|
||||
|
||||
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 testConvertToGeneralizedTime() throws ParseException {
|
||||
String object1 = "20061005093637.44";
|
||||
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss.S");
|
||||
Date expected = df.parse("20061005093637.44");
|
||||
|
||||
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 testConvertToGeneralizedTimeArray() throws ParseException {
|
||||
String object1 = "20071105093655.44";
|
||||
String object2 = "20061005093637.44";
|
||||
Object objectToTranslate = new String[] { object1, object2 };
|
||||
|
||||
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss.S");
|
||||
Date expected = df.parse("20061005093637.44");
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
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, 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 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);
|
||||
}
|
||||
}
|
||||
|
||||
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 };
|
||||
|
||||
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 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 testConvertToLongArray() {
|
||||
String object1 = "878787";
|
||||
String object2 = "23948787";
|
||||
Object objectToTranslate = new String[] { object1, object2 };
|
||||
|
||||
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 testConvertToInteger() {
|
||||
String object1 = "9887342";
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user