LDAP-262: Cleaned up and consolidated the samples.

This commit is contained in:
Mattias Hellborg Arthursson
2013-09-12 07:34:11 +02:00
parent 742ce2b2fe
commit 9458b80fa1
115 changed files with 244 additions and 5866 deletions

View File

@@ -540,13 +540,14 @@ public final class LdapUtils {
* @param index The 0-based index of the rdn value to retrieve. Must be in the range [0,size()).
* @return the value of the rdn at the requested index.
* @throws IndexOutOfBoundsException if index is outside the specified range.
* @since 2.0
*/
public static Object getValue(Name name, int index) {
Assert.notNull(name, "name must not be null");
LdapName ldapName = returnOrConstructLdapNameFromName(name);
Rdn rdn = ldapName.getRdn(index);
if(rdn.size() > 0) {
if(rdn.size() > 1) {
logger.warn("Rdn at position " + index + " of dn '" + name +
"' is multi-value - returned value is not to be trusted. " +
"Consider using name-based getValue method instead");
@@ -562,6 +563,7 @@ public final class LdapUtils {
* @return the value of the rdn at the requested index as a String.
* @throws IndexOutOfBoundsException if index is outside the specified range.
* @throws ClassCastException if the value of the requested component is not a String.
* @since 2.0
*/
public static String getStringValue(Name name, int index) {
return (String) getValue(name, index);

View File

@@ -1,4 +0,0 @@
target
.classpath
.project
.settings

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.0.6.v200806241357]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
<enableImports><![CDATA[false]]></enableImports>
<configs>
<config>src/main/webapp/WEB-INF/applicationContext.xml</config>
<config>src/main/webapp/WEB-INF/basic-servlet.xml</config>
<config>src/test/resources/config/testContext.xml</config>
</configs>
<configSets>
<configSet>
<name><![CDATA[web]]></name>
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
<config>src/main/webapp/WEB-INF/applicationContext.xml</config>
<config>src/main/webapp/WEB-INF/basic-servlet.xml</config>
</configs>
</configSet>
</configSets>
</beansProjectDescription>

View File

@@ -1,25 +0,0 @@
apply from: JAVA_SCRIPT
apply plugin: 'war'
apply plugin: 'jetty'
ext.springVersion = "2.0.8"
dependencies {
compile project(':spring-ldap-test'),
project(':spring-ldap-samples-utils'),
'log4j:log4j:1.2.9',
'javax.servlet:jstl:1.2',
"org.springframework:spring-beans:$springVersion",
"org.springframework:spring-core:$springVersion",
"org.springframework:spring-dao:$springVersion",
"org.springframework:spring-jdbc:$springVersion",
"org.springframework:spring-context:$springVersion",
"org.springframework:spring-web:$springVersion",
"org.springframework:spring-webmvc:$springVersion",
"org.springframework:spring-support:$springVersion"
provided "javax.servlet:servlet-api:2.5"
testCompile "org.springframework:spring-mock:$springVersion",
"junit:junit:$junitVersion"
}

View File

@@ -1,21 +0,0 @@
Uses Spring 2.0.
Sample application demonstrating how to do the most basic stuff in Spring LDAP.
A very simple dao implementation is provided in
org.springframework.ldap.samples.article.dao.PersonDaoImpl
It demonstrates some basic operations using Spring LDAP. For reference purposes,
a corresponding implementation using ordinary Java LDAP/JNDI implementation is
available in TraditionalPersonDaoImpl.
How to use:
-----------
The project is in a Maven build structure. Make sure you have installed the samples-utils artifact, as this will be
needed for this project to work.
'mvn jetty:run' will start up a web server demonstrating the capabilities. The web application will be available
under http://localhost:8080/spring-ldap-person-article-spring20/
'mvn eclipse:eclipse' will construct an Eclipse project for you to use. Import that project into Eclipse using
File/Import/Existing Project, and select this directory.
'mvn test' will run some integration tests that require the LDAP server to be running. It's recommended to run
'mvn jetty:run' from another terminal window before 'mvn test'.

View File

@@ -1,163 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.samples.article.domain.Person;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.ldap.support.LdapUtils;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.util.List;
/**
* Default implementation of PersonDao. This implementation uses
* DirContextAdapter for managing attribute values. It has been specified in the
* Spring Context that the DirObjectFactory should be used when creating objects
* from contexts, which defaults to creating DirContextAdapter objects. This
* means that we can use a ContextMapper to map from the found contexts to our
* domain objects. This is especially useful since we in this case have
* properties in our domain objects that depend on parts of the DN.
*
* We could have worked with Attributes and an AttributesMapper implementation
* instead, but working with Attributes is a bore and also, working with
* AttributesMapper objects (or, indeed Attributes) does not give us access to
* the distinguished name. However, we do use it in one method that only needs a
* single attribute: {@link #getAllPersonNames()}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
Name dn = buildDn(person);
DirContextAdapter context = new DirContextAdapter(dn);
mapToContext(person, context);
ldapTemplate.bind(dn, context, null);
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
Name dn = buildDn(person);
DirContextAdapter context = (DirContextAdapter) ldapTemplate.lookup(dn);
mapToContext(person, context);
ldapTemplate.modifyAttributes(dn, context.getModificationItems());
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
ldapTemplate.unbind(buildDn(person));
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List getAllPersonNames() {
EqualsFilter filter = new EqualsFilter("objectclass", "person");
return ldapTemplate.search(LdapUtils.emptyLdapName(), filter.encode(), new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs) throws NamingException {
return attrs.get("cn").get();
}
});
}
/*
* @see PersonDao#findAll()
*/
public List findAll() {
EqualsFilter filter = new EqualsFilter("objectclass", "person");
return ldapTemplate.search(LdapUtils.emptyLdapName(), filter.encode(), getContextMapper());
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country, String company, String fullname) {
Name dn = buildDn(country, company, fullname);
return (Person) ldapTemplate.lookup(dn, getContextMapper());
}
private ContextMapper getContextMapper() {
return new PersonContextMapper();
}
private Name buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person.getFullName());
}
private Name buildDn(String country, String company, String fullname) {
return LdapNameBuilder.newInstance()
.add("c", country)
.add("ou", company)
.add("cn", fullname)
.build();
}
private void mapToContext(Person person, DirContextAdapter context) {
context.setAttributeValues("objectclass", new String[] { "top", "person" });
context.setAttributeValue("cn", person.getFullName());
context.setAttributeValue("sn", person.getLastName());
context.setAttributeValue("description", person.getDescription());
context.setAttributeValue("telephoneNumber", person.getPhone());
}
/**
* Maps from DirContextAdapter to Person objects. A DN for a person will be
* of the form <code>cn=[fullname],ou=[company],c=[country]</code>, so
* the values of these attributes must be extracted from the DN. For this,
* we use LdapName and helper methods in LdapUtils.
*
*Mattias Hellborg Arthurssonellborg Arthursson
* @author Ulrik Sandberg
*/
private static class PersonContextMapper implements ContextMapper {
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter) ctx;
Name dn = context.getDn();
Person person = new Person();
person.setCountry(LdapUtils.getStringValue(dn, 0));
person.setCompany(LdapUtils.getStringValue(dn, 1));
person.setFullName(context.getStringAttribute("cn"));
person.setLastName(context.getStringAttribute("sn"));
person.setDescription(context.getStringAttribute("description"));
person.setPhone(context.getStringAttribute("telephoneNumber"));
return person;
}
}
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
}

View File

@@ -1,377 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.samples.article.domain.Person;
/**
* Traditional implementation of PersonDao. This implementation uses the basic
* JNDI interfaces and classes {@link DirContext}, {@link Attributes},
* {@link Attribute}, and {@link NamingEnumeration}. The purpose is to
* contrast this implementation with that of {@link PersonDaoImpl}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class TraditionalPersonDaoImpl implements
PersonDao {
private String userName;
private String password;
private String url;
private String base;
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
Attributes attrs = getAttributesToBind(person);
ctx.bind(dn, null, attrs);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx
.rebind(
dn, null,
getAttributesToBind(person));
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.unbind(dn);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List getAllPersonNames() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls
.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search(
"", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results
.next();
Attributes attributes = searchResult
.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
list.add(cn);
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findAll()
*/
public List findAll() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls
.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search(
"", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results
.next();
String dn = searchResult.getName();
Attributes attributes = searchResult
.getAttributes();
list.add(mapToPerson(dn, attributes));
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country,
String company, String fullname) {
DirContext ctx = createAnonymousContext();
String dn = buildDn(
country, company, fullname);
try {
Attributes attributes = ctx
.getAttributes(dn);
return mapToPerson(dn, attributes);
} catch (NameNotFoundException e) {
throw new RuntimeException(
"Did not find entry with primary key '"
+ dn + "'", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
private String buildDn(Person person) {
return buildDn(person.getCountry(), person
.getCompany(), person.getFullName());
}
private String buildDn(String country, String company,
String fullname) {
StringBuffer sb = new StringBuffer();
sb.append("cn=");
sb.append(fullname);
sb.append(", ");
sb.append("ou=");
sb.append(company);
sb.append(", ");
sb.append("c=");
sb.append(country);
String dn = sb.toString();
return dn;
}
private DirContext createContext(Hashtable env) {
env.put(
Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
String tempUrl = createUrl();
env.put(Context.PROVIDER_URL, tempUrl);
DirContext ctx;
try {
ctx = new InitialDirContext(env);
} catch (NamingException e) {
throw new RuntimeException(e);
}
return ctx;
}
private DirContext createAnonymousContext() {
Hashtable env = new Hashtable();
return createContext(env);
}
private DirContext createAuthenticatedContext() {
Hashtable env = new Hashtable();
env.put(
Context.SECURITY_AUTHENTICATION,
"simple");
env.put(
Context.SECURITY_PRINCIPAL, userName);
env.put(
Context.SECURITY_CREDENTIALS, password);
return createContext(env);
}
private Attributes getAttributesToBind(
Person person) {
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute(
"objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", person.getFullName());
attrs.put("sn", person.getLastName());
attrs.put("description", person
.getDescription());
attrs.put("telephoneNumber", person
.getPhone());
return attrs;
}
private Person mapToPerson(String dn,
Attributes attributes)
throws NamingException {
Person person = new Person();
person.setFullName((String) attributes.get(
"cn").get());
person.setLastName((String) attributes.get(
"sn").get());
person.setDescription((String) attributes
.get("description").get());
person.setPhone((String) attributes.get(
"telephoneNumber").get());
// Remove any trailing spaces after comma
String cleanedDn = dn
.replaceAll(", *", ",");
String countryMarker = ",c=";
int countryIndex = cleanedDn
.lastIndexOf(countryMarker);
String companyMarker = ",ou=";
int companyIndex = cleanedDn
.lastIndexOf(companyMarker);
String country = cleanedDn
.substring(countryIndex
+ countryMarker.length());
person.setCountry(country);
String company = cleanedDn.substring(
companyIndex + companyMarker.length(),
countryIndex);
person.setCompany(company);
return person;
}
private String createUrl() {
String tempUrl = url;
if (!tempUrl.endsWith("/")) {
tempUrl += "/";
}
if (StringUtils.isNotEmpty(base)) {
tempUrl += base;
}
return tempUrl;
}
public void setUrl(String url) {
this.url = url;
}
public void setBase(String base) {
this.base = base;
}
public void setPassword(String credentials) {
this.password = credentials;
}
public void setUserDn(String principal) {
this.userName = principal;
}
}

View File

@@ -1,104 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.domain;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
* Simple class representing a single person.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class Person {
private String fullName;
private String lastName;
private String description;
private String country;
private String company;
private String phone;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(
this, obj);
}
public int hashCode() {
return HashCodeBuilder
.reflectionHashCode(this);
}
public String toString() {
return ToStringBuilder.reflectionToString(
this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View File

@@ -1,132 +0,0 @@
package org.springframework.ldap.samples.article.web;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.samples.article.dao.PersonDao;
import org.springframework.ldap.samples.article.domain.Person;
import org.springframework.ldap.samples.utils.HtmlRowLdapTreeVisitor;
import org.springframework.ldap.samples.utils.LdapTree;
import org.springframework.ldap.samples.utils.LdapTreeBuilder;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import javax.naming.Name;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* Default controller.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class DefaultController extends MultiActionController {
private LdapTreeBuilder ldapTreeBuilder;
public void setLdapTreeBuilder(LdapTreeBuilder ldapTreeBuilder) {
this.ldapTreeBuilder = ldapTreeBuilder;
}
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
private PersonDao personDao;
public ModelAndView welcomeHandler(HttpServletRequest request, HttpServletResponse response) {
return new ModelAndView("welcome");
}
public ModelAndView showTree(HttpServletRequest request, HttpServletResponse response) {
LdapTree ldapTree = ldapTreeBuilder.getLdapTree(LdapUtils.emptyLdapName());
HtmlRowLdapTreeVisitor visitor = new PersonLinkHtmlRowLdapTreeVisitor();
ldapTree.traverse(visitor);
return new ModelAndView("showTree", "rows", visitor.getRows());
}
public ModelAndView addPerson(HttpServletRequest request, HttpServletResponse response) {
Person person = getPerson();
personDao.create(person);
return showTree(request, response);
}
public ModelAndView updatePhoneNumber(HttpServletRequest request, HttpServletResponse response) {
Person person = personDao.findByPrimaryKey("Sweden", "company1", "John Doe");
person.setPhone(StringUtils.join(new String[] { person.getPhone(), "0" }));
personDao.update(person);
return showTree(request, response);
}
public ModelAndView removePerson(HttpServletRequest request, HttpServletResponse response) {
Person person = getPerson();
personDao.delete(person);
return showTree(request, response);
}
public ModelAndView showPerson(HttpServletRequest request, HttpServletResponse response, Person query) {
String country = query.getCountry();
String company = query.getCompany();
String fullName = query.getFullName();
Person person = personDao.findByPrimaryKey(country, company, fullName);
return new ModelAndView("showPerson", "person", person);
}
private Person getPerson() {
Person person = new Person();
person.setFullName("John Doe");
person.setLastName("Doe");
person.setCompany("company1");
person.setCountry("Sweden");
person.setDescription("Test user");
return person;
}
/**
* Generates appropriate links for person leaves in the tree.
*
* @author Mattias Hellborg Arthursson
*/
private static final class PersonLinkHtmlRowLdapTreeVisitor extends HtmlRowLdapTreeVisitor {
@Override
protected String getLinkForNode(DirContextOperations node) {
String[] objectClassValues = node.getStringAttributes("objectClass");
if (containsValue(objectClassValues, "person")) {
Name dn = node.getDn();
String country = encodeValue(LdapUtils.getStringValue(dn, "c"));
String company = encodeValue(LdapUtils.getStringValue(dn, "ou"));
String fullName = encodeValue(LdapUtils.getStringValue(dn, "cn"));
return "showPerson.do?country=" + country + "&company=" + company + "&fullName=" + fullName;
}
else {
return super.getLinkForNode(node);
}
}
private String encodeValue(String value) {
try {
return URLEncoder.encode(value, "UTF8");
}
catch (UnsupportedEncodingException e) {
// Not supposed to happen
throw new RuntimeException("Unexpected encoding exception", e);
}
}
private boolean containsValue(String[] values, String value) {
for (String oneValue : values) {
if (StringUtils.equals(oneValue, value)) {
return true;
}
}
return false;
}
}
}

View File

@@ -1,3 +0,0 @@
<body>
This document is the API specification for the Spring LDAP Article sample.
</body>

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/ldap.properties" />
</bean>
<bean id="contextSource"
class="org.springframework.ldap.test.TestContextSourceFactoryBean">
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
<property name="defaultPartitionName" value="jayway" />
<property name="principal" value="${userDn}" />
<property name="password" value="${password}" />
<property name="ldifFile" value="/WEB-INF/setup_data.ldif" />
<property name="port" value="18881" />
</bean>
<bean id="ldapTemplate"
class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="ldapTreeBuilder"
class="org.springframework.ldap.samples.utils.LdapTreeBuilder">
<constructor-arg ref="ldapTemplate" />
</bean>
<bean id="personDao"
class="org.springframework.ldap.samples.article.dao.PersonDaoImpl">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
</beans>

View File

@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="propsResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<value>
/welcome.do=welcome
/showTree.do=showTree
/addPerson.do=addPerson
/updatePhoneNumber.do=updatePhoneNumber
/removePerson.do=removePerson
/showPerson.do=showPerson
</value>
</property>
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/*.do=defaultController
</value>
</property>
</bean>
<bean id="defaultController"
class="org.springframework.ldap.samples.article.web.DefaultController">
<property name="ldapTreeBuilder" ref="ldapTreeBuilder"/>
<property name="personDao" ref="personDao"/>
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

View File

@@ -1,4 +0,0 @@
urls=ldap://127.0.0.1:18881
userDn=uid=admin,ou=system
password=secret
base=dc=jayway,dc=se

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="Tiink-preview" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Spring LDAP Basic Example</display-name>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>basic</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/basic-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>basic</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
</web-app>

View File

@@ -1,122 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import java.util.List;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.samples.article.dao.PersonDao;
import org.springframework.ldap.samples.article.domain.Person;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
/**
* Abstract base class for PersonDao integration tests.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public abstract class AbstractPersonDaoIntegrationTest
extends
AbstractDependencyInjectionSpringContextTests {
protected Person person;
protected PersonDao personDao;
protected String[] getConfigLocations() {
return new String[] { "config/testContext.xml" };
}
protected void onSetUp() throws Exception {
super.onSetUp();
person = new Person();
person.setCountry("Sweden");
person.setCompany("company1");
person.setFullName("Some Person");
person.setLastName("Person");
person
.setDescription("Sweden, Company1, Some Person");
person.setPhone("+46 555-123456");
}
protected void onTearDown() throws Exception {
super.onTearDown();
person = null;
personDao = null;
}
/**
* Having a single test method test create, update and delete is not exactly
* the ideal way of testing, since they depend on each other. A better way
* would be to separate the tests and load a test fixture before each
* operation, in order to guarantee the expected state every time. See the
* ldaptemplate-person sample for the correct way to do this.
*/
public void testCreateUpdateDelete() {
try {
person.setFullName("Another Person");
personDao.create(person);
personDao.findByPrimaryKey(
"Sweden", "company1",
"Another Person");
// if we got here, create succeeded
person
.setDescription("Another description");
personDao.update(person);
Person result = personDao
.findByPrimaryKey(
"Sweden", "company1",
"Another Person");
assertEquals(
"Another description", result
.getDescription());
} finally {
personDao.delete(person);
try {
personDao.findByPrimaryKey(
"Sweden", "company1",
"Another Person");
fail("NameNotFoundException (when using Spring LDAP) or RuntimeException (when using traditional) expected");
} catch (NameNotFoundException expected) {
// expected
} catch (RuntimeException expected) {
// expected
}
}
}
public void testGetAllPersonNames() {
List result = personDao.getAllPersonNames();
assertEquals(2, result.size());
String first = (String) result.get(0);
assertEquals("Some Person", first);
}
public void testFindAll() {
List result = personDao.findAll();
assertEquals(2, result.size());
Person first = (Person) result.get(0);
assertEquals("Some Person", first
.getFullName());
}
public void testFindByPrimaryKey() {
Person result = personDao.findByPrimaryKey(
"Sweden", "company1", "Some Person");
assertEquals(person, result);
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import org.springframework.ldap.samples.article.dao.PersonDaoImpl;
/**
* Integration tests for the PersonDaoImpl class.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoImplIntegrationTest extends
AbstractPersonDaoIntegrationTest {
public void setPersonDao(
PersonDaoImpl personDao) {
this.personDao = personDao;
}
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
/**
* Integration tests for the TraditionalPersonDaoImpl class.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class TraditionalPersonDaoImplIntegrationTest
extends AbstractPersonDaoIntegrationTest {
public void setPersonDao(
TraditionalPersonDaoImpl personDao) {
this.personDao = personDao;
}
}

View File

@@ -1,4 +0,0 @@
urls=ldap://127.0.0.1:18881
userDn=uid=admin,ou=system
password=secret
base=dc=jayway,dc=se

View File

@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/config/ldap.properties" />
</bean>
<bean id="contextSource"
class="org.springframework.ldap.test.TestContextSourceFactoryBean">
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
<property name="defaultPartitionName" value="jayway" />
<property name="principal" value="${userDn}" />
<property name="password" value="${password}" />
<property name="ldifFile" value="/setup_data.ldif" />
<property name="port" value="18881" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="personDao"
class="org.springframework.ldap.samples.article.dao.PersonDaoImpl">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
<bean id="traditionalPersonDao"
class="org.springframework.ldap.samples.article.dao.TraditionalPersonDaoImpl">
<property name="url" value="ldap://localhost:18881" />
<property name="base" value="dc=jayway,dc=se" />
<property name="userDn" value="${userDn}" />
<property name="password" value="${password}" />
</bean>
</beans>

View File

@@ -1,4 +0,0 @@
target
.classpath
.project
.settings

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.0.5.v200805211800]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
<enableImports><![CDATA[false]]></enableImports>
<configs>
</configs>
<configSets>
</configSets>
</beansProjectDescription>

View File

@@ -1,23 +0,0 @@
apply from: JAVA_SCRIPT
apply plugin: 'war'
apply plugin: 'jetty'
dependencies {
compile project(':spring-ldap-test'),
project(':spring-ldap-samples-utils'),
'log4j:log4j:1.2.9',
'javax.servlet:jstl:1.2',
"org.springframework:spring-beans:$springVersion",
"org.springframework:spring-core:$springVersion",
"org.springframework:spring-tx:$springVersion",
"org.springframework:spring-jdbc:$springVersion",
"org.springframework:spring-context:$springVersion",
"org.springframework:spring-web:$springVersion",
"org.springframework:spring-webmvc:$springVersion",
"org.springframework:spring-aop:$springVersion"
provided "javax.servlet:servlet-api:2.5"
testCompile "org.springframework:spring-test:$springVersion",
"junit:junit:$junitVersion"
}

View File

@@ -1,21 +0,0 @@
Uses Spring 3.0.
Sample application demonstrating how to do the most basic stuff in Spring LDAP.
A very simple dao implementation is provided in
org.springframework.ldap.samples.article.dao.PersonDaoImpl
It demonstrates some basic operations using Spring LDAP. For reference purposes,
a corresponding implementation using ordinary Java LDAP/JNDI implementation is
available in TraditionalPersonDaoImpl.
How to use:
-----------
The project is in a Maven build structure. Make sure you have installed the samples-utils artifact, as this will be
needed for this project to work.
'mvn jetty:run' will start up a web server demonstrating the capabilities. The web application will be available
under http://localhost:8080/spring-ldap-person-article-spring30/
'mvn eclipse:eclipse' will construct an Eclipse project for you to use. Import that project into Eclipse using
File/Import/Existing Project, and select this directory.
'mvn test' will run some integration tests that require the LDAP server to be running. It's recommended to run
'mvn jetty:run' from another terminal window before 'mvn test'.

View File

@@ -1,42 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import java.util.List;
import org.springframework.ldap.samples.article.domain.Person;
/**
* Data Access Object interface for the Person entity.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public interface PersonDao {
void create(Person person);
void update(Person person);
void delete(Person person);
List getAllPersonNames();
List findAll();
Person findByPrimaryKey(String country,
String company, String fullname);
}

View File

@@ -1,163 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.samples.article.domain.Person;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.ldap.support.LdapUtils;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.util.List;
/**
* Default implementation of PersonDao. This implementation uses
* DirContextAdapter for managing attribute values. It has been specified in the
* Spring Context that the DirObjectFactory should be used when creating objects
* from contexts, which defaults to creating DirContextAdapter objects. This
* means that we can use a ContextMapper to map from the found contexts to our
* domain objects. This is especially useful since we in this case have
* properties in our domain objects that depend on parts of the DN.
*
* We could have worked with Attributes and an AttributesMapper implementation
* instead, but working with Attributes is a bore and also, working with
* AttributesMapper objects (or, indeed Attributes) does not give us access to
* the distinguished name. However, we do use it in one method that only needs a
* single attribute: {@link #getAllPersonNames()}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
Name dn = buildDn(person);
DirContextAdapter context = new DirContextAdapter(dn);
mapToContext(person, context);
ldapTemplate.bind(dn, context, null);
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
Name dn = buildDn(person);
DirContextAdapter context = (DirContextAdapter) ldapTemplate.lookup(dn);
mapToContext(person, context);
ldapTemplate.modifyAttributes(dn, context.getModificationItems());
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
ldapTemplate.unbind(buildDn(person));
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List getAllPersonNames() {
EqualsFilter filter = new EqualsFilter("objectclass", "person");
return ldapTemplate.search(LdapUtils.emptyLdapName(), filter.encode(), new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs) throws NamingException {
return attrs.get("cn").get();
}
});
}
/*
* @see PersonDao#findAll()
*/
public List findAll() {
EqualsFilter filter = new EqualsFilter("objectclass", "person");
return ldapTemplate.search(LdapUtils.emptyLdapName(), filter.encode(), getContextMapper());
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country, String company, String fullname) {
Name dn = buildDn(country, company, fullname);
return (Person) ldapTemplate.lookup(dn, getContextMapper());
}
private ContextMapper getContextMapper() {
return new PersonContextMapper();
}
private Name buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person.getFullName());
}
private Name buildDn(String country, String company, String fullname) {
return LdapNameBuilder.newInstance()
.add("c", country)
.add("ou", company)
.add("cn", fullname)
.build();
}
private void mapToContext(Person person, DirContextAdapter context) {
context.setAttributeValues("objectclass", new String[] { "top", "person" });
context.setAttributeValue("cn", person.getFullName());
context.setAttributeValue("sn", person.getLastName());
context.setAttributeValue("description", person.getDescription());
context.setAttributeValue("telephoneNumber", person.getPhone());
}
/**
* Maps from DirContextAdapter to Person objects. A DN for a person will be
* of the form <code>cn=[fullname],ou=[company],c=[country]</code>, so
* the values of these attributes must be extracted from the DN. For this,
* we use LdapName and utility methods in LdapUtils.
*
*Mattias Hellborg Arthurssonellborg Arthursson
* @author Ulrik Sandberg
*/
private static class PersonContextMapper implements ContextMapper {
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter) ctx;
Name dn = context.getDn();
Person person = new Person();
person.setCountry(LdapUtils.getStringValue(dn, 0));
person.setCompany(LdapUtils.getStringValue(dn, 1));
person.setFullName(context.getStringAttribute("cn"));
person.setLastName(context.getStringAttribute("sn"));
person.setDescription(context.getStringAttribute("description"));
person.setPhone(context.getStringAttribute("telephoneNumber"));
return person;
}
}
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
}

View File

@@ -1,377 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.samples.article.domain.Person;
/**
* Traditional implementation of PersonDao. This implementation uses the basic
* JNDI interfaces and classes {@link DirContext}, {@link Attributes},
* {@link Attribute}, and {@link NamingEnumeration}. The purpose is to
* contrast this implementation with that of {@link PersonDaoImpl}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class TraditionalPersonDaoImpl implements
PersonDao {
private String userName;
private String password;
private String url;
private String base;
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
Attributes attrs = getAttributesToBind(person);
ctx.bind(dn, null, attrs);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx
.rebind(
dn, null,
getAttributesToBind(person));
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.unbind(dn);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List getAllPersonNames() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls
.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search(
"", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results
.next();
Attributes attributes = searchResult
.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
list.add(cn);
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findAll()
*/
public List findAll() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls
.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search(
"", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results
.next();
String dn = searchResult.getName();
Attributes attributes = searchResult
.getAttributes();
list.add(mapToPerson(dn, attributes));
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country,
String company, String fullname) {
DirContext ctx = createAnonymousContext();
String dn = buildDn(
country, company, fullname);
try {
Attributes attributes = ctx
.getAttributes(dn);
return mapToPerson(dn, attributes);
} catch (NameNotFoundException e) {
throw new RuntimeException(
"Did not find entry with primary key '"
+ dn + "'", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
private String buildDn(Person person) {
return buildDn(person.getCountry(), person
.getCompany(), person.getFullName());
}
private String buildDn(String country, String company,
String fullname) {
StringBuffer sb = new StringBuffer();
sb.append("cn=");
sb.append(fullname);
sb.append(", ");
sb.append("ou=");
sb.append(company);
sb.append(", ");
sb.append("c=");
sb.append(country);
String dn = sb.toString();
return dn;
}
private DirContext createContext(Hashtable env) {
env.put(
Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
String tempUrl = createUrl();
env.put(Context.PROVIDER_URL, tempUrl);
DirContext ctx;
try {
ctx = new InitialDirContext(env);
} catch (NamingException e) {
throw new RuntimeException(e);
}
return ctx;
}
private DirContext createAnonymousContext() {
Hashtable env = new Hashtable();
return createContext(env);
}
private DirContext createAuthenticatedContext() {
Hashtable env = new Hashtable();
env.put(
Context.SECURITY_AUTHENTICATION,
"simple");
env.put(
Context.SECURITY_PRINCIPAL, userName);
env.put(
Context.SECURITY_CREDENTIALS, password);
return createContext(env);
}
private Attributes getAttributesToBind(
Person person) {
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute(
"objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", person.getFullName());
attrs.put("sn", person.getLastName());
attrs.put("description", person
.getDescription());
attrs.put("telephoneNumber", person
.getPhone());
return attrs;
}
private Person mapToPerson(String dn,
Attributes attributes)
throws NamingException {
Person person = new Person();
person.setFullName((String) attributes.get(
"cn").get());
person.setLastName((String) attributes.get(
"sn").get());
person.setDescription((String) attributes
.get("description").get());
person.setPhone((String) attributes.get(
"telephoneNumber").get());
// Remove any trailing spaces after comma
String cleanedDn = dn
.replaceAll(", *", ",");
String countryMarker = ",c=";
int countryIndex = cleanedDn
.lastIndexOf(countryMarker);
String companyMarker = ",ou=";
int companyIndex = cleanedDn
.lastIndexOf(companyMarker);
String country = cleanedDn
.substring(countryIndex
+ countryMarker.length());
person.setCountry(country);
String company = cleanedDn.substring(
companyIndex + companyMarker.length(),
countryIndex);
person.setCompany(company);
return person;
}
private String createUrl() {
String tempUrl = url;
if (!tempUrl.endsWith("/")) {
tempUrl += "/";
}
if (StringUtils.isNotEmpty(base)) {
tempUrl += base;
}
return tempUrl;
}
public void setUrl(String url) {
this.url = url;
}
public void setBase(String base) {
this.base = base;
}
public void setPassword(String credentials) {
this.password = credentials;
}
public void setUserDn(String principal) {
this.userName = principal;
}
}

View File

@@ -1,104 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.domain;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
* Simple class representing a single person.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class Person {
private String fullName;
private String lastName;
private String description;
private String country;
private String company;
private String phone;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(
this, obj);
}
public int hashCode() {
return HashCodeBuilder
.reflectionHashCode(this);
}
public String toString() {
return ToStringBuilder.reflectionToString(
this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View File

@@ -1,130 +0,0 @@
package org.springframework.ldap.samples.article.web;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.samples.article.dao.PersonDao;
import org.springframework.ldap.samples.article.domain.Person;
import org.springframework.ldap.samples.utils.HtmlRowLdapTreeVisitor;
import org.springframework.ldap.samples.utils.LdapTree;
import org.springframework.ldap.samples.utils.LdapTreeBuilder;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.naming.Name;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* Default controller.
*
* @author Mattias Hellborg Arthursson
*/
@Controller
public class DefaultController {
@Autowired
private LdapTreeBuilder ldapTreeBuilder;
@Autowired
private PersonDao personDao;
@RequestMapping("/welcome.do")
public void welcomeHandler() {
}
@RequestMapping("/showTree.do")
public ModelAndView showTree() {
LdapTree ldapTree = ldapTreeBuilder.getLdapTree(LdapUtils.emptyLdapName());
HtmlRowLdapTreeVisitor visitor = new PersonLinkHtmlRowLdapTreeVisitor();
ldapTree.traverse(visitor);
return new ModelAndView("showTree", "rows", visitor.getRows());
}
@RequestMapping("/addPerson.do")
public ModelAndView addPerson() {
Person person = getPerson();
personDao.create(person);
return showTree();
}
@RequestMapping("/updatePhoneNumber.do")
public ModelAndView updatePhoneNumber() {
Person person = personDao.findByPrimaryKey("Sweden", "company1", "John Doe");
person.setPhone(StringUtils.join(new String[] { person.getPhone(), "0" }));
personDao.update(person);
return showTree();
}
@RequestMapping("/removePerson.do")
public ModelAndView removePerson() {
Person person = getPerson();
personDao.delete(person);
return showTree();
}
@RequestMapping("/showPerson.do")
public ModelMap showPerson(String country, String company, String fullName) {
Person person = personDao.findByPrimaryKey(country, company, fullName);
return new ModelMap("person", person);
}
private Person getPerson() {
Person person = new Person();
person.setFullName("John Doe");
person.setLastName("Doe");
person.setCompany("company1");
person.setCountry("Sweden");
person.setDescription("Test user");
return person;
}
/**
* Generates appropriate links for person leaves in the tree.
*
* @author Mattias Hellborg Arthursson
*/
private static final class PersonLinkHtmlRowLdapTreeVisitor extends HtmlRowLdapTreeVisitor {
@Override
protected String getLinkForNode(DirContextOperations node) {
String[] objectClassValues = node.getStringAttributes("objectClass");
if (containsValue(objectClassValues, "person")) {
Name dn = node.getDn();
String country = encodeValue(LdapUtils.getStringValue(dn, "c"));
String company = encodeValue(LdapUtils.getStringValue(dn, "ou"));
String fullName = encodeValue(LdapUtils.getStringValue(dn, "cn"));
return "showPerson.do?country=" + country + "&company=" + company + "&fullName=" + fullName;
}
else {
return super.getLinkForNode(node);
}
}
private String encodeValue(String value) {
try {
return URLEncoder.encode(value, "UTF8");
}
catch (UnsupportedEncodingException e) {
// Not supposed to happen
throw new RuntimeException("Unexpected encoding exception", e);
}
}
private boolean containsValue(String[] values, String value) {
for (String oneValue : values) {
if (StringUtils.equals(oneValue, value)) {
return true;
}
}
return false;
}
}
}

View File

@@ -1,3 +0,0 @@
<body>
This document is the API specification for the Spring LDAP Article sample.
</body>

View File

@@ -1,7 +0,0 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.logger.org.apache.directory=ERROR

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/ldap.properties" />
</bean>
<bean id="contextSource"
class="org.springframework.ldap.test.TestContextSourceFactoryBean">
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
<property name="defaultPartitionName" value="jayway" />
<property name="principal" value="${userDn}" />
<property name="password" value="${password}" />
<property name="ldifFile" value="/WEB-INF/setup_data.ldif" />
<property name="port" value="18882" />
</bean>
z
<bean id="ldapTemplate"
class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="ldapTreeBuilder"
class="org.springframework.ldap.samples.utils.LdapTreeBuilder">
<constructor-arg ref="ldapTemplate" />
</bean>
<bean id="personDao"
class="org.springframework.ldap.samples.article.dao.PersonDaoImpl">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
</beans>

View File

@@ -1,20 +0,0 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<a href="showTree.do">Back</a>
<p>
Full name: ${person.fullName}
<br>
LastName: ${person.lastName}
<br>
Description: ${person.description}
<br>
Country: ${person.country}
<br>
Company: ${person.company}
<br>
Phone: ${person.phone}
<br>
</p>
</html>

View File

@@ -1,17 +0,0 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<h2>Operations</h2>
<h3>Clicking a link below performs the described operation which will be reflected in the LDAP tree below</h3>
<a href="addPerson.do">Add new test person 'John Doe'</a> (only works once)<br>
<a href="updatePhoneNumber.do">Add a '0' to the phone number of test person</a> (only works if the person has been created)<br>
<a href="removePerson.do">Remove test person</a><br>
<p>
<h2>Tree contents</h2>
<h3>Click a person row to see the attribute values (country and company rows do not have additional info)</h3>
<c:forEach var="row" items="${rows}">
${row}
</c:forEach>
</p>
</body>
</html>

View File

@@ -1,4 +0,0 @@
urls=ldap://127.0.0.1:18882
userDn=uid=admin,ou=system
password=secret
base=dc=jayway,dc=se

View File

@@ -1,35 +0,0 @@
dn: c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-123456
dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person2
userPassword: password
cn: Some Person2
sn: Person2
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="Tiink-preview" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Spring LDAP Basic Example</display-name>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>basic</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/basic-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>basic</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
</web-app>

View File

@@ -1,5 +0,0 @@
<html>
<head>
<meta HTTP-EQUIV="REFRESH" content="0; url=showTree.do">
</head>
</html>

View File

@@ -1,122 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import java.util.List;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.samples.article.dao.PersonDao;
import org.springframework.ldap.samples.article.domain.Person;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
/**
* Abstract base class for PersonDao integration tests.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public abstract class AbstractPersonDaoIntegrationTest
extends
AbstractDependencyInjectionSpringContextTests {
protected Person person;
protected PersonDao personDao;
protected String[] getConfigLocations() {
return new String[] { "config/testContext.xml" };
}
protected void onSetUp() throws Exception {
super.onSetUp();
person = new Person();
person.setCountry("Sweden");
person.setCompany("company1");
person.setFullName("Some Person");
person.setLastName("Person");
person
.setDescription("Sweden, Company1, Some Person");
person.setPhone("+46 555-123456");
}
protected void onTearDown() throws Exception {
super.onTearDown();
person = null;
personDao = null;
}
/**
* Having a single test method test create, update and delete is not exactly
* the ideal way of testing, since they depend on each other. A better way
* would be to separate the tests and load a test fixture before each
* operation, in order to guarantee the expected state every time. See the
* ldaptemplate-person sample for the correct way to do this.
*/
public void testCreateUpdateDelete() {
try {
person.setFullName("Another Person");
personDao.create(person);
personDao.findByPrimaryKey(
"Sweden", "company1",
"Another Person");
// if we got here, create succeeded
person
.setDescription("Another description");
personDao.update(person);
Person result = personDao
.findByPrimaryKey(
"Sweden", "company1",
"Another Person");
assertEquals(
"Another description", result
.getDescription());
} finally {
personDao.delete(person);
try {
personDao.findByPrimaryKey(
"Sweden", "company1",
"Another Person");
fail("NameNotFoundException (when using Spring LDAP) or RuntimeException (when using traditional) expected");
} catch (NameNotFoundException expected) {
// expected
} catch (RuntimeException expected) {
// expected
}
}
}
public void testGetAllPersonNames() {
List result = personDao.getAllPersonNames();
assertEquals(2, result.size());
String first = (String) result.get(0);
assertEquals("Some Person", first);
}
public void testFindAll() {
List result = personDao.findAll();
assertEquals(2, result.size());
Person first = (Person) result.get(0);
assertEquals("Some Person", first
.getFullName());
}
public void testFindByPrimaryKey() {
Person result = personDao.findByPrimaryKey(
"Sweden", "company1", "Some Person");
assertEquals(person, result);
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import org.springframework.ldap.samples.article.dao.PersonDaoImpl;
/**
* Integration tests for the PersonDaoImpl class.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoImplIntegrationTest extends
AbstractPersonDaoIntegrationTest {
public void setPersonDao(
PersonDaoImpl personDao) {
this.personDao = personDao;
}
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
/**
* Integration tests for the TraditionalPersonDaoImpl class.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class TraditionalPersonDaoImplIntegrationTest
extends AbstractPersonDaoIntegrationTest {
public void setPersonDao(
TraditionalPersonDaoImpl personDao) {
this.personDao = personDao;
}
}

View File

@@ -1,4 +0,0 @@
urls=ldap://127.0.0.1:18882
userDn=uid=admin,ou=system
password=secret
base=dc=jayway,dc=se

View File

@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/config/ldap.properties" />
</bean>
<bean id="contextSource"
class="org.springframework.ldap.test.TestContextSourceFactoryBean">
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
<property name="defaultPartitionName" value="jayway" />
<property name="principal" value="${userDn}" />
<property name="password" value="${password}" />
<property name="ldifFile" value="/setup_data.ldif" />
<property name="port" value="18882" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="personDao"
class="org.springframework.ldap.samples.article.dao.PersonDaoImpl">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
<bean id="traditionalPersonDao"
class="org.springframework.ldap.samples.article.dao.TraditionalPersonDaoImpl">
<property name="url" value="ldap://localhost:18882" />
<property name="base" value="dc=jayway,dc=se" />
<property name="userDn" value="${userDn}" />
<property name="password" value="${password}" />
</bean>
</beans>

View File

@@ -1,35 +0,0 @@
dn: c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-123456
dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person2
userPassword: password
cn: Some Person2
sn: Person2
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321

View File

@@ -1,4 +0,0 @@
target
.classpath
.project
.settings

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.0.5.v200805211800]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
<enableImports><![CDATA[false]]></enableImports>
<configs>
</configs>
<configSets>
</configSets>
</beansProjectDescription>

View File

@@ -1,20 +0,0 @@
Sample application demonstrating how to do the most basic stuff in Spring LDAP.
A very simple dao implementation is provided in
org.springframework.ldap.samples.article.dao.PersonDaoImpl
It demonstrates some basic operations using Spring LDAP. For reference purposes,
a corresponding implementation using ordinary Java LDAP/JNDI implementation is
available in TraditionalPersonDaoImpl.
How to use:
-----------
The project is in a Maven build structure. Make sure you have installed the samples-utils artifact, as this will be
needed for this project to work.
'mvn jetty:run' will start up a web server demonstrating the capabilities. The web application will be available
under http://localhost:8080/spring-ldap-person-article/
'mvn eclipse:eclipse' will construct an Eclipse project for you to use. Import that project into Eclipse using
File/Import/Existing Project, and select this directory.
'mvn test' will run some integration tests that require the LDAP server to be running. It's recommended to run
'mvn jetty:run' from another terminal window before 'mvn test'.

View File

@@ -1,42 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import java.util.List;
import org.springframework.ldap.samples.article.domain.Person;
/**
* Data Access Object interface for the Person entity.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public interface PersonDao {
void create(Person person);
void update(Person person);
void delete(Person person);
List getAllPersonNames();
List findAll();
Person findByPrimaryKey(String country,
String company, String fullname);
}

View File

@@ -1,377 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.samples.article.domain.Person;
/**
* Traditional implementation of PersonDao. This implementation uses the basic
* JNDI interfaces and classes {@link DirContext}, {@link Attributes},
* {@link Attribute}, and {@link NamingEnumeration}. The purpose is to
* contrast this implementation with that of {@link PersonDaoImpl}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class TraditionalPersonDaoImpl implements
PersonDao {
private String userName;
private String password;
private String url;
private String base;
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
Attributes attrs = getAttributesToBind(person);
ctx.bind(dn, null, attrs);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx
.rebind(
dn, null,
getAttributesToBind(person));
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.unbind(dn);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List getAllPersonNames() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls
.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search(
"", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results
.next();
Attributes attributes = searchResult
.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
list.add(cn);
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findAll()
*/
public List findAll() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls
.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search(
"", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results
.next();
String dn = searchResult.getName();
Attributes attributes = searchResult
.getAttributes();
list.add(mapToPerson(dn, attributes));
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country,
String company, String fullname) {
DirContext ctx = createAnonymousContext();
String dn = buildDn(
country, company, fullname);
try {
Attributes attributes = ctx
.getAttributes(dn);
return mapToPerson(dn, attributes);
} catch (NameNotFoundException e) {
throw new RuntimeException(
"Did not find entry with primary key '"
+ dn + "'", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
private String buildDn(Person person) {
return buildDn(person.getCountry(), person
.getCompany(), person.getFullName());
}
private String buildDn(String country, String company,
String fullname) {
StringBuffer sb = new StringBuffer();
sb.append("cn=");
sb.append(fullname);
sb.append(", ");
sb.append("ou=");
sb.append(company);
sb.append(", ");
sb.append("c=");
sb.append(country);
String dn = sb.toString();
return dn;
}
private DirContext createContext(Hashtable env) {
env.put(
Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
String tempUrl = createUrl();
env.put(Context.PROVIDER_URL, tempUrl);
DirContext ctx;
try {
ctx = new InitialDirContext(env);
} catch (NamingException e) {
throw new RuntimeException(e);
}
return ctx;
}
private DirContext createAnonymousContext() {
Hashtable env = new Hashtable();
return createContext(env);
}
private DirContext createAuthenticatedContext() {
Hashtable env = new Hashtable();
env.put(
Context.SECURITY_AUTHENTICATION,
"simple");
env.put(
Context.SECURITY_PRINCIPAL, userName);
env.put(
Context.SECURITY_CREDENTIALS, password);
return createContext(env);
}
private Attributes getAttributesToBind(
Person person) {
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute(
"objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", person.getFullName());
attrs.put("sn", person.getLastName());
attrs.put("description", person
.getDescription());
attrs.put("telephoneNumber", person
.getPhone());
return attrs;
}
private Person mapToPerson(String dn,
Attributes attributes)
throws NamingException {
Person person = new Person();
person.setFullName((String) attributes.get(
"cn").get());
person.setLastName((String) attributes.get(
"sn").get());
person.setDescription((String) attributes
.get("description").get());
person.setPhone((String) attributes.get(
"telephoneNumber").get());
// Remove any trailing spaces after comma
String cleanedDn = dn
.replaceAll(", *", ",");
String countryMarker = ",c=";
int countryIndex = cleanedDn
.lastIndexOf(countryMarker);
String companyMarker = ",ou=";
int companyIndex = cleanedDn
.lastIndexOf(companyMarker);
String country = cleanedDn
.substring(countryIndex
+ countryMarker.length());
person.setCountry(country);
String company = cleanedDn.substring(
companyIndex + companyMarker.length(),
countryIndex);
person.setCompany(company);
return person;
}
private String createUrl() {
String tempUrl = url;
if (!tempUrl.endsWith("/")) {
tempUrl += "/";
}
if (StringUtils.isNotEmpty(base)) {
tempUrl += base;
}
return tempUrl;
}
public void setUrl(String url) {
this.url = url;
}
public void setBase(String base) {
this.base = base;
}
public void setPassword(String credentials) {
this.password = credentials;
}
public void setUserDn(String principal) {
this.userName = principal;
}
}

View File

@@ -1,104 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.domain;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
* Simple class representing a single person.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class Person {
private String fullName;
private String lastName;
private String description;
private String country;
private String company;
private String phone;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(
this, obj);
}
public int hashCode() {
return HashCodeBuilder
.reflectionHashCode(this);
}
public String toString() {
return ToStringBuilder.reflectionToString(
this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View File

@@ -1,3 +0,0 @@
<body>
This document is the API specification for the Spring LDAP Article sample.
</body>

View File

@@ -1,7 +0,0 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.logger.org.apache.directory=ERROR

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/ldap.properties" />
</bean>
<bean id="contextSource"
class="org.springframework.ldap.test.TestContextSourceFactoryBean">
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
<property name="defaultPartitionName" value="jayway" />
<property name="principal" value="${userDn}" />
<property name="password" value="${password}" />
<property name="ldifFile" value="/WEB-INF/setup_data.ldif" />
<property name="port" value="18880" />
</bean>
<bean id="ldapTemplate"
class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="ldapTreeBuilder"
class="org.springframework.ldap.samples.utils.LdapTreeBuilder">
<constructor-arg ref="ldapTemplate" />
</bean>
<bean id="personDao"
class="org.springframework.ldap.samples.article.dao.PersonDaoImpl">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
</beans>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan
base-package="org.springframework.ldap.samples.article.web" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

View File

@@ -1,20 +0,0 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<a href="showTree.do">Back</a>
<p>
Full name: ${person.fullName}
<br>
LastName: ${person.lastName}
<br>
Description: ${person.description}
<br>
Country: ${person.country}
<br>
Company: ${person.company}
<br>
Phone: ${person.phone}
<br>
</p>
</html>

View File

@@ -1,17 +0,0 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<h2>Operations</h2>
<h3>Clicking a link below performs the described operation which will be reflected in the LDAP tree below</h3>
<a href="addPerson.do">Add new test person 'John Doe'</a> (only works once)<br>
<a href="updatePhoneNumber.do">Add a '0' to the phone number of test person</a> (only works if the person has been created)<br>
<a href="removePerson.do">Remove test person</a><br>
<p>
<h2>Tree contents</h2>
<h3>Click a person row to see the attribute values (country and company rows do not have additional info)</h3>
<c:forEach var="row" items="${rows}">
${row}
</c:forEach>
</p>
</body>
</html>

View File

@@ -1,35 +0,0 @@
dn: c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-123456
dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person2
userPassword: password
cn: Some Person2
sn: Person2
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321

View File

@@ -1,5 +0,0 @@
<html>
<head>
<meta HTTP-EQUIV="REFRESH" content="0; url=showTree.do">
</head>
</html>

View File

@@ -1,122 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import java.util.List;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.samples.article.dao.PersonDao;
import org.springframework.ldap.samples.article.domain.Person;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
/**
* Abstract base class for PersonDao integration tests.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public abstract class AbstractPersonDaoIntegrationTest
extends
AbstractDependencyInjectionSpringContextTests {
protected Person person;
protected PersonDao personDao;
protected String[] getConfigLocations() {
return new String[] { "config/testContext.xml" };
}
protected void onSetUp() throws Exception {
super.onSetUp();
person = new Person();
person.setCountry("Sweden");
person.setCompany("company1");
person.setFullName("Some Person");
person.setLastName("Person");
person
.setDescription("Sweden, Company1, Some Person");
person.setPhone("+46 555-123456");
}
protected void onTearDown() throws Exception {
super.onTearDown();
person = null;
personDao = null;
}
/**
* Having a single test method test create, update and delete is not exactly
* the ideal way of testing, since they depend on each other. A better way
* would be to separate the tests and load a test fixture before each
* operation, in order to guarantee the expected state every time. See the
* ldaptemplate-person sample for the correct way to do this.
*/
public void testCreateUpdateDelete() {
try {
person.setFullName("Another Person");
personDao.create(person);
personDao.findByPrimaryKey(
"Sweden", "company1",
"Another Person");
// if we got here, create succeeded
person
.setDescription("Another description");
personDao.update(person);
Person result = personDao
.findByPrimaryKey(
"Sweden", "company1",
"Another Person");
assertEquals(
"Another description", result
.getDescription());
} finally {
personDao.delete(person);
try {
personDao.findByPrimaryKey(
"Sweden", "company1",
"Another Person");
fail("NameNotFoundException (when using Spring LDAP) or RuntimeException (when using traditional) expected");
} catch (NameNotFoundException expected) {
// expected
} catch (RuntimeException expected) {
// expected
}
}
}
public void testGetAllPersonNames() {
List result = personDao.getAllPersonNames();
assertEquals(2, result.size());
String first = (String) result.get(0);
assertEquals("Some Person", first);
}
public void testFindAll() {
List result = personDao.findAll();
assertEquals(2, result.size());
Person first = (Person) result.get(0);
assertEquals("Some Person", first
.getFullName());
}
public void testFindByPrimaryKey() {
Person result = personDao.findByPrimaryKey(
"Sweden", "company1", "Some Person");
assertEquals(person, result);
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
import org.springframework.ldap.samples.article.dao.PersonDaoImpl;
/**
* Integration tests for the PersonDaoImpl class.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoImplIntegrationTest extends
AbstractPersonDaoIntegrationTest {
public void setPersonDao(
PersonDaoImpl personDao) {
this.personDao = personDao;
}
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
/**
* Integration tests for the TraditionalPersonDaoImpl class.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class TraditionalPersonDaoImplIntegrationTest
extends AbstractPersonDaoIntegrationTest {
public void setPersonDao(
TraditionalPersonDaoImpl personDao) {
this.personDao = personDao;
}
}

View File

@@ -1,35 +0,0 @@
dn: c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-123456
dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person2
userPassword: password
cn: Some Person2
sn: Person2
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321

View File

@@ -1,4 +0,0 @@
target
.classpath
.project
.settings

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.0.6.v200806241357]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
<enableImports><![CDATA[false]]></enableImports>
<configs>
<config>src/test/resources/config/testContext.xml</config>
</configs>
<configSets>
<configSet>
<name><![CDATA[web]]></name>
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
</configs>
</configSet>
</configSets>
</beansProjectDescription>

View File

@@ -1,12 +0,0 @@
apply from: JAVA_SCRIPT
description = "Example code for demonstrating the process of refactoring from plain JNDI to Spring LDAP (Java 5)."
dependencies {
compile project(':spring-ldap-test'),
project(':spring-ldap-core-tiger'),
"org.springframework:spring-context:$springVersion"
testCompile "org.springframework:spring-test:$springVersion",
"junit:junit:$junitVersion"
}

View File

@@ -1,18 +0,0 @@
Demo application to be used for demonstrating how to convert a legacy JNDI-based
dao implementation written in Java 1.4 to instead use Spring LDAP. For reference
purposes, a corresponding implementation using ordinary Java LDAP/JNDI
implementation is available in TraditionalPersonDaoImpl.
How to use:
-----------
'mvn test' will start up an LDAP server before running the integration tests that
verify the dao implementation.
'mvn eclipse:eclipse' will construct an Eclipse project for you to use. Import
that project into Eclipse using File/Import/Existing Project, and select this
directory.
You can start converting the org.springframework.ldap.demo.dao.PersonDaoImpl class.
The original traditional implementation, as well as a "solution", is available in
the org.springframework.ldap.demo.solution package. Run the tests after you have
converted a method.

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.dao;
import java.util.List;
import org.springframework.ldap.demo.domain.Person;
/**
* Data Access Object interface for the Person entity.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public interface PersonDao {
void create(Person person);
void update(Person person);
void delete(Person person);
List<String> getAllPersonNames();
List<Person> findAll();
Person findByPrimaryKey(String country, String company, String fullname);
}

View File

@@ -1,344 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.dao;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.demo.dao.PersonDao;
import org.springframework.ldap.demo.domain.Person;
/**
* Traditional implementation of PersonDao. This implementation uses the basic
* JNDI interfaces and classes {@link DirContext}, {@link Attributes},
* {@link Attribute}, and {@link NamingEnumeration}. The purpose is to contrast
* this implementation with an implementation based on Spring LDAP.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoImpl implements PersonDao {
private String userName;
private String password;
private String url;
private String base;
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
Attributes attrs = getAttributesToBind(person);
ctx.bind(dn, null, attrs);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.rebind(dn, null, getAttributesToBind(person));
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.unbind(dn);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List<String> getAllPersonNames() {
DirContext ctx = createAnonymousContext();
LinkedList<String> list = new LinkedList<String>();
NamingEnumeration<?> results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
Attributes attributes = searchResult.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
list.add(cn);
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findAll()
*/
public List<Person> findAll() {
DirContext ctx = createAnonymousContext();
LinkedList<Person> list = new LinkedList<Person>();
NamingEnumeration<?> results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
String dn = searchResult.getName();
Attributes attributes = searchResult.getAttributes();
list.add(mapToPerson(dn, attributes));
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country, String company,
String fullname) {
DirContext ctx = createAnonymousContext();
String dn = buildDn(country, company, fullname);
try {
Attributes attributes = ctx.getAttributes(dn);
return mapToPerson(dn, attributes);
} catch (NameNotFoundException e) {
throw new RuntimeException("Did not find entry with primary key '"
+ dn + "'", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
private String buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person
.getFullName());
}
private String buildDn(String country, String company, String fullname) {
StringBuffer sb = new StringBuffer();
sb.append("cn=");
sb.append(fullname);
sb.append(", ");
sb.append("ou=");
sb.append(company);
sb.append(", ");
sb.append("c=");
sb.append(country);
String dn = sb.toString();
return dn;
}
private DirContext createContext(Hashtable<String, String> env) {
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
String tempUrl = createUrl();
env.put(Context.PROVIDER_URL, tempUrl);
DirContext ctx;
try {
ctx = new InitialDirContext(env);
} catch (NamingException e) {
throw new RuntimeException(e);
}
return ctx;
}
private DirContext createAnonymousContext() {
Hashtable<String, String> hashtable = new Hashtable<String, String>();
Hashtable<String, String> env = hashtable;
return createContext(env);
}
private DirContext createAuthenticatedContext() {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, userName);
env.put(Context.SECURITY_CREDENTIALS, password);
return createContext(env);
}
private Attributes getAttributesToBind(Person person) {
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute("objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", person.getFullName());
attrs.put("sn", person.getLastName());
attrs.put("description", person.getDescription());
attrs.put("telephoneNumber", person.getPhone());
return attrs;
}
private Person mapToPerson(String dn, Attributes attributes)
throws NamingException {
Person person = new Person();
person.setFullName((String) attributes.get("cn").get());
person.setLastName((String) attributes.get("sn").get());
person.setDescription((String) attributes.get("description").get());
person.setPhone((String) attributes.get("telephoneNumber").get());
// Remove any trailing spaces after comma
String cleanedDn = dn.replaceAll(", *", ",");
String countryMarker = ",c=";
int countryIndex = cleanedDn.lastIndexOf(countryMarker);
String companyMarker = ",ou=";
int companyIndex = cleanedDn.lastIndexOf(companyMarker);
String country = cleanedDn.substring(countryIndex
+ countryMarker.length());
person.setCountry(country);
String company = cleanedDn.substring(companyIndex
+ companyMarker.length(), countryIndex);
person.setCompany(company);
return person;
}
private String createUrl() {
String tempUrl = url;
if (!tempUrl.endsWith("/")) {
tempUrl += "/";
}
if (StringUtils.isNotEmpty(base)) {
tempUrl += base;
}
return tempUrl;
}
public void setUrl(String url) {
this.url = url;
}
public void setBase(String base) {
this.base = base;
}
public void setPassword(String credentials) {
this.password = credentials;
}
public void setUserDn(String principal) {
this.userName = principal;
}
}

View File

@@ -1,104 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.domain;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
* Simple class representing a single person.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class Person {
private String fullName;
private String lastName;
private String description;
private String country;
private String company;
private String phone;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(
this, obj);
}
public int hashCode() {
return HashCodeBuilder
.reflectionHashCode(this);
}
public String toString() {
return ToStringBuilder.reflectionToString(
this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View File

@@ -1,140 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.solution;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.simple.AbstractParameterizedContextMapper;
import org.springframework.ldap.core.simple.SimpleLdapTemplate;
import org.springframework.ldap.demo.dao.PersonDao;
import org.springframework.ldap.demo.domain.Person;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.ldap.support.LdapUtils;
import javax.naming.Name;
import java.util.List;
/**
* Spring LDAP implementation of PersonDao. This implementation uses many Spring
* LDAP features, such as the {@link DirContextAdapter},
* {@link AbstractParameterizedContextMapper}, and {@link SimpleLdapTemplate}. The purpose is to
* contrast this implementation with that of {@link TraditionalPersonDaoImpl}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoImpl implements PersonDao {
private static final class PersonContextMapper extends
AbstractParameterizedContextMapper<Person> {
@Override
protected Person doMapFromContext(DirContextOperations ctx) {
Person person = new Person();
person.setFullName(ctx.getStringAttribute("cn"));
person.setLastName(ctx.getStringAttribute("sn"));
person.setDescription(ctx.getStringAttribute("description"));
person.setPhone(ctx.getStringAttribute("telephoneNumber"));
Name dn = ctx.getDn();
person.setCountry(LdapUtils.getStringValue(dn, "c"));
person.setCompany(LdapUtils.getStringValue(dn, "ou"));
return person;
}
}
private SimpleLdapTemplate ldapTemplate;
public void setLdapTemplate(SimpleLdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
DirContextOperations ctx = new DirContextAdapter(buildDn(person));
mapToContext(person, ctx);
ldapTemplate.bind(ctx);
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
DirContextOperations ctx = ldapTemplate.lookupContext(buildDn(person));
mapToContext(person, ctx);
ldapTemplate.modifyAttributes(ctx);
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
ldapTemplate.unbind(buildDn(person));
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List<String> getAllPersonNames() {
return ldapTemplate.search("", "(objectclass=person)",
new AbstractParameterizedContextMapper<String>() {
@Override
protected String doMapFromContext(DirContextOperations ctx) {
return ctx.getStringAttribute("cn");
}
});
}
/*
* @see PersonDao#findAll()
*/
public List<Person> findAll() {
return ldapTemplate.search("", "(objectclass=person)",
new PersonContextMapper());
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country, String company,
String fullname) {
Name dn = buildDn(country, company, fullname);
return (Person) ldapTemplate.lookup(dn, new PersonContextMapper());
}
private Name buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person
.getFullName());
}
private Name buildDn(String country, String company, String fullname) {
return LdapNameBuilder.newInstance()
.add("c", country)
.add("ou", company)
.add("cn", fullname)
.build();
}
private void mapToContext(Person person, DirContextOperations ctx) {
ctx.setAttributeValues("objectclass", new String[] { "top", "person" });
ctx.setAttributeValue("cn", person.getFullName());
ctx.setAttributeValue("sn", person.getLastName());
ctx.setAttributeValue("description", person.getDescription());
ctx.setAttributeValue("telephoneNumber", person.getPhone());
}
}

View File

@@ -1,344 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.solution;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.demo.dao.PersonDao;
import org.springframework.ldap.demo.domain.Person;
/**
* Traditional implementation of PersonDao. This implementation uses the basic
* JNDI interfaces and classes {@link DirContext}, {@link Attributes},
* {@link Attribute}, and {@link NamingEnumeration}. The purpose is to contrast
* this implementation with an implementation based on Spring LDAP.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class TraditionalPersonDaoImpl implements PersonDao {
private String userName;
private String password;
private String url;
private String base;
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
Attributes attrs = getAttributesToBind(person);
ctx.bind(dn, null, attrs);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.rebind(dn, null, getAttributesToBind(person));
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.unbind(dn);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List<String> getAllPersonNames() {
DirContext ctx = createAnonymousContext();
LinkedList<String> list = new LinkedList<String>();
NamingEnumeration<?> results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
Attributes attributes = searchResult.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
list.add(cn);
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findAll()
*/
public List<Person> findAll() {
DirContext ctx = createAnonymousContext();
LinkedList<Person> list = new LinkedList<Person>();
NamingEnumeration<?> results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
String dn = searchResult.getName();
Attributes attributes = searchResult.getAttributes();
list.add(mapToPerson(dn, attributes));
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country, String company,
String fullname) {
DirContext ctx = createAnonymousContext();
String dn = buildDn(country, company, fullname);
try {
Attributes attributes = ctx.getAttributes(dn);
return mapToPerson(dn, attributes);
} catch (NameNotFoundException e) {
throw new RuntimeException("Did not find entry with primary key '"
+ dn + "'", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
private String buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person
.getFullName());
}
private String buildDn(String country, String company, String fullname) {
StringBuffer sb = new StringBuffer();
sb.append("cn=");
sb.append(fullname);
sb.append(", ");
sb.append("ou=");
sb.append(company);
sb.append(", ");
sb.append("c=");
sb.append(country);
String dn = sb.toString();
return dn;
}
private DirContext createContext(Hashtable<String, String> env) {
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
String tempUrl = createUrl();
env.put(Context.PROVIDER_URL, tempUrl);
DirContext ctx;
try {
ctx = new InitialDirContext(env);
} catch (NamingException e) {
throw new RuntimeException(e);
}
return ctx;
}
private DirContext createAnonymousContext() {
Hashtable<String, String> hashtable = new Hashtable<String, String>();
Hashtable<String, String> env = hashtable;
return createContext(env);
}
private DirContext createAuthenticatedContext() {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, userName);
env.put(Context.SECURITY_CREDENTIALS, password);
return createContext(env);
}
private Attributes getAttributesToBind(Person person) {
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute("objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", person.getFullName());
attrs.put("sn", person.getLastName());
attrs.put("description", person.getDescription());
attrs.put("telephoneNumber", person.getPhone());
return attrs;
}
private Person mapToPerson(String dn, Attributes attributes)
throws NamingException {
Person person = new Person();
person.setFullName((String) attributes.get("cn").get());
person.setLastName((String) attributes.get("sn").get());
person.setDescription((String) attributes.get("description").get());
person.setPhone((String) attributes.get("telephoneNumber").get());
// Remove any trailing spaces after comma
String cleanedDn = dn.replaceAll(", *", ",");
String countryMarker = ",c=";
int countryIndex = cleanedDn.lastIndexOf(countryMarker);
String companyMarker = ",ou=";
int companyIndex = cleanedDn.lastIndexOf(companyMarker);
String country = cleanedDn.substring(countryIndex
+ countryMarker.length());
person.setCountry(country);
String company = cleanedDn.substring(companyIndex
+ companyMarker.length(), countryIndex);
person.setCompany(company);
return person;
}
private String createUrl() {
String tempUrl = url;
if (!tempUrl.endsWith("/")) {
tempUrl += "/";
}
if (StringUtils.isNotEmpty(base)) {
tempUrl += base;
}
return tempUrl;
}
public void setUrl(String url) {
this.url = url;
}
public void setBase(String base) {
this.base = base;
}
public void setPassword(String credentials) {
this.password = credentials;
}
public void setUserDn(String principal) {
this.userName = principal;
}
}

View File

@@ -1,3 +0,0 @@
<body>
This document is the API specification for the Spring LDAP Article sample.
</body>

View File

@@ -1,118 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.dao;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.demo.domain.Person;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
/**
* Integration tests for the PersonDao class.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
@ContextConfiguration(locations = { "/config/testContext.xml" })
public class PersonDaoIntegrationTest extends AbstractJUnit4SpringContextTests {
private Person person;
@Autowired
private PersonDao personDao;
@Before
public void setUp() throws Exception {
person = new Person();
person.setCountry("Sweden");
person.setCompany("company1");
person.setFullName("Some Person");
person.setLastName("Person");
person.setDescription("Sweden, Company1, Some Person");
person.setPhone("+46 555-123456");
}
@After
public void tearDown() throws Exception {
person = null;
personDao = null;
}
/**
* Having a single test method test create, update and delete is not exactly
* the ideal way of testing, since they depend on each other. A better way
* would be to separate the tests and load a test fixture before each
* operation, in order to guarantee the expected state every time.
*/
@Test
public void testCreateUpdateDelete() {
try {
person.setFullName("Another Person");
personDao.create(person);
personDao.findByPrimaryKey("Sweden", "company1", "Another Person");
// if we got here, create succeeded
person.setDescription("Another description");
personDao.update(person);
Person result = personDao.findByPrimaryKey("Sweden", "company1",
"Another Person");
assertEquals("Another description", result.getDescription());
} finally {
personDao.delete(person);
try {
personDao.findByPrimaryKey("Sweden", "company1",
"Another Person");
fail("NameNotFoundException (when using Spring LDAP) or RuntimeException (when using traditional) expected");
} catch (NameNotFoundException expected) {
// expected
} catch (RuntimeException expected) {
// expected
}
}
}
@Test
public void testGetAllPersonNames() {
List<String> result = personDao.getAllPersonNames();
assertEquals(2, result.size());
String first = (String) result.get(0);
assertEquals("Some Person", first);
}
@Test
public void testFindAll() {
List<Person> result = personDao.findAll();
assertEquals(2, result.size());
Person first = (Person) result.get(0);
assertEquals("Some Person", first.getFullName());
}
@Test
public void testFindByPrimaryKey() {
Person result = personDao.findByPrimaryKey("Sweden", "company1",
"Some Person");
assertEquals(person, result);
}
}

View File

@@ -1,4 +0,0 @@
urls=ldap://127.0.0.1:18884
userDn=uid=admin,ou=system
password=secret
base=dc=jayway,dc=se

View File

@@ -1,35 +0,0 @@
dn: c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-123456
dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person2
userPassword: password
cn: Some Person2
sn: Person2
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/config/ldap.properties" />
</bean>
<bean id="contextSource"
class="org.springframework.ldap.test.TestContextSourceFactoryBean">
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
<property name="defaultPartitionName" value="jayway" />
<property name="principal" value="${userDn}" />
<property name="password" value="${password}" />
<property name="ldifFile" value="/config/setup_data.ldif" />
<property name="port" value="18884" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="personDao" class="org.springframework.ldap.demo.dao.PersonDaoImpl">
<property name="base" value="dc=jayway,dc=se" />
<property name="url" value="ldap://localhost:18884" />
<property name="userDn" value="${userDn}" />
<property name="password" value="${password}" />
</bean>
</beans>

View File

@@ -1,7 +0,0 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.logger.org.apache.directory=ERROR

View File

@@ -1,4 +0,0 @@
target
.classpath
.project
.settings

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.0.6.v200806241357]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
<enableImports><![CDATA[false]]></enableImports>
<configs>
<config>src/test/resources/config/testContext.xml</config>
</configs>
<configSets>
<configSet>
<name><![CDATA[web]]></name>
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
</configs>
</configSet>
</configSets>
</beansProjectDescription>

View File

@@ -1,12 +0,0 @@
apply from: JAVA_SCRIPT
description = "Example code for demonstrating the process of refactoring from plain JNDI to Spring LDAP (Java 1.4)."
dependencies {
compile project(':spring-ldap-test'),
project(':spring-ldap-core'),
"org.springframework:spring-context:$springVersion"
testCompile "org.springframework:spring-test:$springVersion",
"junit:junit:$junitVersion"
}

View File

@@ -1,18 +0,0 @@
Demo application to be used for demonstrating how to convert a legacy JNDI-based
dao implementation written in Java 1.4 to use Spring LDAP, focussing on the Java5
support in Spring LDAP. For reference purposes, a corresponding implementation
using ordinary Java LDAP/JNDI implementation is available in TraditionalPersonDaoImpl.
How to use:
-----------
'mvn test' will start up an LDAP server before running the integration tests that
verify the dao implementation.
'mvn eclipse:eclipse' will construct an Eclipse project for you to use. Import
that project into Eclipse using File/Import/Existing Project, and select this
directory.
You can start converting the org.springframework.ldap.demo.dao.PersonDaoImpl class.
The original traditional implementation, as well as a "solution", is available in
the org.springframework.ldap.demo.solution package. Run the tests after you have
converted a method.

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.dao;
import java.util.List;
import org.springframework.ldap.demo.domain.Person;
/**
* Data Access Object interface for the Person entity.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public interface PersonDao {
void create(Person person);
void update(Person person);
void delete(Person person);
List getAllPersonNames();
List findAll();
Person findByPrimaryKey(String country, String company, String fullname);
}

View File

@@ -1,343 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.dao;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.demo.domain.Person;
/**
* Traditional implementation of PersonDao. This implementation uses the basic
* JNDI interfaces and classes {@link DirContext}, {@link Attributes},
* {@link Attribute}, and {@link NamingEnumeration}. The purpose is to contrast
* this implementation with an implementation based on Spring LDAP.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoImpl implements PersonDao {
private String userName;
private String password;
private String url;
private String base;
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
Attributes attrs = getAttributesToBind(person);
ctx.bind(dn, null, attrs);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.rebind(dn, null, getAttributesToBind(person));
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.unbind(dn);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List getAllPersonNames() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
Attributes attributes = searchResult.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
list.add(cn);
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findAll()
*/
public List findAll() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
String dn = searchResult.getName();
Attributes attributes = searchResult.getAttributes();
list.add(mapToPerson(dn, attributes));
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country, String company,
String fullname) {
DirContext ctx = createAnonymousContext();
String dn = buildDn(country, company, fullname);
try {
Attributes attributes = ctx.getAttributes(dn);
return mapToPerson(dn, attributes);
} catch (NameNotFoundException e) {
throw new RuntimeException("Did not find entry with primary key '"
+ dn + "'", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
private String buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person
.getFullName());
}
private String buildDn(String country, String company, String fullname) {
StringBuffer sb = new StringBuffer();
sb.append("cn=");
sb.append(fullname);
sb.append(", ");
sb.append("ou=");
sb.append(company);
sb.append(", ");
sb.append("c=");
sb.append(country);
String dn = sb.toString();
return dn;
}
private DirContext createContext(Hashtable env) {
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
String tempUrl = createUrl();
env.put(Context.PROVIDER_URL, tempUrl);
DirContext ctx;
try {
ctx = new InitialDirContext(env);
} catch (NamingException e) {
throw new RuntimeException(e);
}
return ctx;
}
private DirContext createAnonymousContext() {
Hashtable hashtable = new Hashtable();
Hashtable env = hashtable;
return createContext(env);
}
private DirContext createAuthenticatedContext() {
Hashtable env = new Hashtable();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, userName);
env.put(Context.SECURITY_CREDENTIALS, password);
return createContext(env);
}
private Attributes getAttributesToBind(Person person) {
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute("objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", person.getFullName());
attrs.put("sn", person.getLastName());
attrs.put("description", person.getDescription());
attrs.put("telephoneNumber", person.getPhone());
return attrs;
}
private Person mapToPerson(String dn, Attributes attributes)
throws NamingException {
Person person = new Person();
person.setFullName((String) attributes.get("cn").get());
person.setLastName((String) attributes.get("sn").get());
person.setDescription((String) attributes.get("description").get());
person.setPhone((String) attributes.get("telephoneNumber").get());
// Remove any trailing spaces after comma
String cleanedDn = dn.replaceAll(", *", ",");
String countryMarker = ",c=";
int countryIndex = cleanedDn.lastIndexOf(countryMarker);
String companyMarker = ",ou=";
int companyIndex = cleanedDn.lastIndexOf(companyMarker);
String country = cleanedDn.substring(countryIndex
+ countryMarker.length());
person.setCountry(country);
String company = cleanedDn.substring(companyIndex
+ companyMarker.length(), countryIndex);
person.setCompany(company);
return person;
}
private String createUrl() {
String tempUrl = url;
if (!tempUrl.endsWith("/")) {
tempUrl += "/";
}
if (StringUtils.isNotEmpty(base)) {
tempUrl += base;
}
return tempUrl;
}
public void setUrl(String url) {
this.url = url;
}
public void setBase(String base) {
this.base = base;
}
public void setPassword(String credentials) {
this.password = credentials;
}
public void setUserDn(String principal) {
this.userName = principal;
}
}

View File

@@ -1,138 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.solution;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.demo.dao.PersonDao;
import org.springframework.ldap.demo.domain.Person;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.ldap.support.LdapUtils;
import javax.naming.Name;
import java.util.List;
/**
* Spring LDAP implementation of PersonDao. This implementation uses many Spring
* LDAP features, such as the {@link DirContextAdapter},
* {@link AbstractContextMapper}, and {@link LdapTemplate}. The purpose is to
* contrast this implementation with that of {@link TraditionalPersonDaoImpl}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoImpl implements PersonDao {
private static final class PersonContextMapper extends
AbstractContextMapper {
protected Object doMapFromContext(DirContextOperations ctx) {
Person person = new Person();
person.setFullName(ctx.getStringAttribute("cn"));
person.setLastName(ctx.getStringAttribute("sn"));
person.setDescription(ctx.getStringAttribute("description"));
person.setPhone(ctx.getStringAttribute("telephoneNumber"));
Name dn = ctx.getDn();
person.setCountry(LdapUtils.getStringValue(dn, "c"));
person.setCompany(LdapUtils.getStringValue(dn, "ou"));
return person;
}
}
private LdapTemplate ldapTemplate;
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
DirContextOperations ctx = new DirContextAdapter(buildDn(person));
mapToContext(person, ctx);
ldapTemplate.bind(ctx);
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
DirContextOperations ctx = ldapTemplate.lookupContext(buildDn(person));
mapToContext(person, ctx);
ldapTemplate.modifyAttributes(ctx);
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
ldapTemplate.unbind(buildDn(person));
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List getAllPersonNames() {
return ldapTemplate.search("", "(objectclass=person)",
new AbstractContextMapper() {
protected Object doMapFromContext(DirContextOperations ctx) {
return ctx.getStringAttribute("cn");
}
});
}
/*
* @see PersonDao#findAll()
*/
public List findAll() {
return ldapTemplate.search("", "(objectclass=person)",
new PersonContextMapper());
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country, String company,
String fullname) {
Name dn = buildDn(country, company, fullname);
return (Person) ldapTemplate.lookup(dn, new PersonContextMapper());
}
private Name buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person
.getFullName());
}
private Name buildDn(String country, String company, String fullname) {
return LdapNameBuilder.newInstance()
.add("c", country)
.add("ou", company)
.add("cn", fullname)
.build();
}
private void mapToContext(Person person, DirContextOperations ctx) {
ctx.setAttributeValues("objectclass", new String[] { "top", "person" });
ctx.setAttributeValue("cn", person.getFullName());
ctx.setAttributeValue("sn", person.getLastName());
ctx.setAttributeValue("description", person.getDescription());
ctx.setAttributeValue("telephoneNumber", person.getPhone());
}
}

View File

@@ -1,344 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.solution;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.demo.dao.PersonDao;
import org.springframework.ldap.demo.domain.Person;
/**
* Traditional implementation of PersonDao. This implementation uses the basic
* JNDI interfaces and classes {@link DirContext}, {@link Attributes},
* {@link Attribute}, and {@link NamingEnumeration}. The purpose is to contrast
* this implementation with an implementation based on Spring LDAP.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class TraditionalPersonDaoImpl implements PersonDao {
private String userName;
private String password;
private String url;
private String base;
/*
* @see PersonDao#create(Person)
*/
public void create(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
Attributes attrs = getAttributesToBind(person);
ctx.bind(dn, null, attrs);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#update(Person)
*/
public void update(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.rebind(dn, null, getAttributesToBind(person));
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#delete(Person)
*/
public void delete(Person person) {
DirContext ctx = createAuthenticatedContext();
String dn = buildDn(person);
try {
ctx.unbind(dn);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List getAllPersonNames() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
Attributes attributes = searchResult.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
list.add(cn);
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findAll()
*/
public List findAll() {
DirContext ctx = createAnonymousContext();
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
String dn = searchResult.getName();
Attributes attributes = searchResult.getAttributes();
list.add(mapToPerson(dn, attributes));
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
// Never mind this.
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
return list;
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country, String company,
String fullname) {
DirContext ctx = createAnonymousContext();
String dn = buildDn(country, company, fullname);
try {
Attributes attributes = ctx.getAttributes(dn);
return mapToPerson(dn, attributes);
} catch (NameNotFoundException e) {
throw new RuntimeException("Did not find entry with primary key '"
+ dn + "'", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
// Never mind this.
}
}
}
}
private String buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person
.getFullName());
}
private String buildDn(String country, String company, String fullname) {
StringBuffer sb = new StringBuffer();
sb.append("cn=");
sb.append(fullname);
sb.append(", ");
sb.append("ou=");
sb.append(company);
sb.append(", ");
sb.append("c=");
sb.append(country);
String dn = sb.toString();
return dn;
}
private DirContext createContext(Hashtable env) {
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
String tempUrl = createUrl();
env.put(Context.PROVIDER_URL, tempUrl);
DirContext ctx;
try {
ctx = new InitialDirContext(env);
} catch (NamingException e) {
throw new RuntimeException(e);
}
return ctx;
}
private DirContext createAnonymousContext() {
Hashtable hashtable = new Hashtable();
Hashtable env = hashtable;
return createContext(env);
}
private DirContext createAuthenticatedContext() {
Hashtable env = new Hashtable();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, userName);
env.put(Context.SECURITY_CREDENTIALS, password);
return createContext(env);
}
private Attributes getAttributesToBind(Person person) {
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute("objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", person.getFullName());
attrs.put("sn", person.getLastName());
attrs.put("description", person.getDescription());
attrs.put("telephoneNumber", person.getPhone());
return attrs;
}
private Person mapToPerson(String dn, Attributes attributes)
throws NamingException {
Person person = new Person();
person.setFullName((String) attributes.get("cn").get());
person.setLastName((String) attributes.get("sn").get());
person.setDescription((String) attributes.get("description").get());
person.setPhone((String) attributes.get("telephoneNumber").get());
// Remove any trailing spaces after comma
String cleanedDn = dn.replaceAll(", *", ",");
String countryMarker = ",c=";
int countryIndex = cleanedDn.lastIndexOf(countryMarker);
String companyMarker = ",ou=";
int companyIndex = cleanedDn.lastIndexOf(companyMarker);
String country = cleanedDn.substring(countryIndex
+ countryMarker.length());
person.setCountry(country);
String company = cleanedDn.substring(companyIndex
+ companyMarker.length(), countryIndex);
person.setCompany(company);
return person;
}
private String createUrl() {
String tempUrl = url;
if (!tempUrl.endsWith("/")) {
tempUrl += "/";
}
if (StringUtils.isNotEmpty(base)) {
tempUrl += base;
}
return tempUrl;
}
public void setUrl(String url) {
this.url = url;
}
public void setBase(String base) {
this.base = base;
}
public void setPassword(String credentials) {
this.password = credentials;
}
public void setUserDn(String principal) {
this.userName = principal;
}
}

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/config/ldap.properties" />
</bean>
<bean id="contextSource"
class="org.springframework.ldap.test.TestContextSourceFactoryBean">
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
<property name="defaultPartitionName" value="jayway" />
<property name="principal" value="${userDn}" />
<property name="password" value="${password}" />
<property name="ldifFile" value="/config/setup_data.ldif" />
<property name="port" value="18883" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="personDao" class="org.springframework.ldap.demo.dao.PersonDaoImpl">
<property name="url" value="ldap://127.0.0.1:18883" />
<property name="base" value="dc=jayway,dc=se" />
<property name="userDn" value="${userDn}" />
<property name="password" value="${password}" />
</bean>
</beans>

View File

@@ -1,3 +0,0 @@
<body>
This document is the API specification for the Spring LDAP Article sample.
</body>

View File

@@ -1,113 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.dao;
import java.util.List;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.demo.domain.Person;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
/**
* Integration tests for the PersonDao class.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonDaoIntegrationTest extends
AbstractDependencyInjectionSpringContextTests {
private Person person;
private PersonDao personDao;
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
protected String[] getConfigLocations() {
return new String[] { "/config/testContext.xml" };
}
protected void onSetUp() throws Exception {
super.onSetUp();
person = new Person();
person.setCountry("Sweden");
person.setCompany("company1");
person.setFullName("Some Person");
person.setLastName("Person");
person.setDescription("Sweden, Company1, Some Person");
person.setPhone("+46 555-123456");
}
protected void onTearDown() throws Exception {
super.onTearDown();
person = null;
personDao = null;
}
/**
* Having a single test method test create, update and delete is not exactly
* the ideal way of testing, since they depend on each other. A better way
* would be to separate the tests and load a test fixture before each
* operation, in order to guarantee the expected state every time.
*/
public void testCreateUpdateDelete() {
try {
person.setFullName("Another Person");
personDao.create(person);
personDao.findByPrimaryKey("Sweden", "company1", "Another Person");
// if we got here, create succeeded
person.setDescription("Another description");
personDao.update(person);
Person result = personDao.findByPrimaryKey("Sweden", "company1",
"Another Person");
assertEquals("Another description", result.getDescription());
} finally {
personDao.delete(person);
try {
personDao.findByPrimaryKey("Sweden", "company1",
"Another Person");
fail("NameNotFoundException (when using Spring LDAP) or RuntimeException (when using traditional) expected");
} catch (NameNotFoundException expected) {
// expected
} catch (RuntimeException expected) {
// expected
}
}
}
public void testGetAllPersonNames() {
List result = personDao.getAllPersonNames();
assertEquals(2, result.size());
String first = (String) result.get(0);
assertEquals("Some Person", first);
}
public void testFindAll() {
List result = personDao.findAll();
assertEquals(2, result.size());
Person first = (Person) result.get(0);
assertEquals("Some Person", first.getFullName());
}
public void testFindByPrimaryKey() {
Person result = personDao.findByPrimaryKey("Sweden", "company1",
"Some Person");
assertEquals(person, result);
}
}

View File

@@ -1,4 +0,0 @@
urls=ldap://127.0.0.1:18883
userDn=uid=admin,ou=system
password=secret
base=dc=jayway,dc=se

View File

@@ -1,35 +0,0 @@
dn: c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-123456
dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person2
userPassword: password
cn: Some Person2
sn: Person2
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/config/ldap.properties" />
</bean>
<bean id="contextSource"
class="org.springframework.ldap.test.TestContextSourceFactoryBean">
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
<property name="defaultPartitionName" value="jayway" />
<property name="principal" value="${userDn}" />
<property name="password" value="${password}" />
<property name="ldifFile" value="/config/setup_data.ldif" />
<property name="port" value="18883" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="personDao" class="org.springframework.ldap.demo.dao.PersonDaoImpl">
<property name="base" value="dc=jayway,dc=se" />
<property name="url" value="ldap://localhost:18883" />
<property name="userDn" value="${userDn}" />
<property name="password" value="${password}" />
</bean>
</beans>

View File

@@ -1,7 +0,0 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.logger.org.apache.directory=ERROR

View File

@@ -1 +0,0 @@
Demo applications for demonstrating conversion of legacy JNDI to Spring LDAP.

9
samples/plain/readme.txt Normal file
View File

@@ -0,0 +1,9 @@
Sample application demonstrating how to do the most basic stuff in Spring LDAP.
A very simple dao implementation is provided in org.springframework.ldap.samples.plain.dao.PersonDaoImpl
It demonstrates some basic operations using Spring LDAP.
The core Spring application context of the sample is defined in resources/applicationContext.xml.
This ApplicationContext will start an in-process Apache Directory Server instance, automatically populated
with some test data. The data will be reset every time the application is restarted.
To run the example, do 'gradle jettyRun', and then navigate to http://localhost:8080/spring-ldap-plain-sample

View File

@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
package org.springframework.ldap.samples.plain.dao;
import org.springframework.ldap.samples.plain.domain.Person;
import java.util.List;
import org.springframework.ldap.samples.article.domain.Person;
/**
* Data Access Object interface for the Person entity.
@@ -33,10 +33,9 @@ public interface PersonDao {
void delete(Person person);
List getAllPersonNames();
List<String> getAllPersonNames();
List findAll();
List<Person> findAll();
Person findByPrimaryKey(String country,
String company, String fullname);
Person findByPrimaryKey(String country, String company, String fullname);
}

View File

@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.samples.article.dao;
package org.springframework.ldap.samples.plain.dao;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.samples.article.domain.Person;
import org.springframework.ldap.samples.plain.domain.Person;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.ldap.support.LdapUtils;
@@ -32,12 +34,9 @@ import java.util.List;
/**
* Default implementation of PersonDao. This implementation uses
* DirContextAdapter for managing attribute values. It has been specified in the
* Spring Context that the DirObjectFactory should be used when creating objects
* from contexts, which defaults to creating DirContextAdapter objects. This
* means that we can use a ContextMapper to map from the found contexts to our
* domain objects. This is especially useful since we in this case have
* properties in our domain objects that depend on parts of the DN.
* DirContextAdapter for managing attribute values. We use a ContextMapper
* to map from the found contexts to our domain objects. This is especially useful
* since we in this case have properties in our domain objects that depend on parts of the DN.
*
* We could have worked with Attributes and an AttributesMapper implementation
* instead, but working with Attributes is a bore and also, working with
@@ -52,9 +51,7 @@ public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
/*
* @see PersonDao#create(Person)
*/
@Override
public void create(Person person) {
Name dn = buildDn(person);
DirContextAdapter context = new DirContextAdapter(dn);
@@ -62,9 +59,7 @@ public class PersonDaoImpl implements PersonDao {
ldapTemplate.bind(dn, context, null);
}
/*
* @see PersonDao#update(Person)
*/
@Override
public void update(Person person) {
Name dn = buildDn(person);
DirContextAdapter context = (DirContextAdapter) ldapTemplate.lookup(dn);
@@ -72,44 +67,31 @@ public class PersonDaoImpl implements PersonDao {
ldapTemplate.modifyAttributes(dn, context.getModificationItems());
}
/*
* @see PersonDao#delete(Person)
*/
@Override
public void delete(Person person) {
ldapTemplate.unbind(buildDn(person));
}
/*
* @see PersonDao#getAllPersonNames()
*/
public List getAllPersonNames() {
@Override
public List<String> getAllPersonNames() {
EqualsFilter filter = new EqualsFilter("objectclass", "person");
return ldapTemplate.search(LdapUtils.emptyLdapName(), filter.encode(), new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs) throws NamingException {
return attrs.get("cn").get();
return ldapTemplate.search(LdapUtils.emptyLdapName(), filter.encode(), new AttributesMapper<String>() {
public String mapFromAttributes(Attributes attrs) throws NamingException {
return attrs.get("cn").get().toString();
}
});
}
/*
* @see PersonDao#findAll()
*/
public List findAll() {
@Override
public List<Person> findAll() {
EqualsFilter filter = new EqualsFilter("objectclass", "person");
return ldapTemplate.search(LdapUtils.emptyLdapName(), filter.encode(), getContextMapper());
return ldapTemplate.search(LdapUtils.emptyLdapName(), filter.encode(), PERSON_CONTEXT_MAPPER);
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
@Override
public Person findByPrimaryKey(String country, String company, String fullname) {
LdapName dn = buildDn(country, company, fullname);
return (Person) ldapTemplate.lookup(dn, getContextMapper());
}
private ContextMapper getContextMapper() {
return new PersonContextMapper();
return ldapTemplate.lookup(dn, PERSON_CONTEXT_MAPPER);
}
private LdapName buildDn(Person person) {
@@ -137,16 +119,13 @@ public class PersonDaoImpl implements PersonDao {
* of the form <code>cn=[fullname],ou=[company],c=[country]</code>, so
* the values of these attributes must be extracted from the DN. For this,
* we use the LdapName along with utility methods in LdapUtils.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
private static class PersonContextMapper implements ContextMapper {
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter) ctx;
LdapName dn = LdapUtils.newLdapName(context.getDn());
private final static ContextMapper<Person> PERSON_CONTEXT_MAPPER = new AbstractContextMapper<Person>() {
@Override
public Person doMapFromContext(DirContextOperations context) {
Person person = new Person();
LdapName dn = LdapUtils.newLdapName(context.getDn());
person.setCountry(LdapUtils.getStringValue(dn, 0));
person.setCompany(LdapUtils.getStringValue(dn, 1));
person.setFullName(context.getStringAttribute("cn"));
@@ -156,7 +135,7 @@ public class PersonDaoImpl implements PersonDao {
return person;
}
}
};
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.demo.domain;
package org.springframework.ldap.samples.plain.domain;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

View File

@@ -1,10 +1,10 @@
package org.springframework.ldap.samples.article.web;
package org.springframework.ldap.samples.plain.web;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.samples.article.dao.PersonDao;
import org.springframework.ldap.samples.article.domain.Person;
import org.springframework.ldap.samples.plain.dao.PersonDao;
import org.springframework.ldap.samples.plain.domain.Person;
import org.springframework.ldap.samples.utils.HtmlRowLdapTreeVisitor;
import org.springframework.ldap.samples.utils.LdapTree;
import org.springframework.ldap.samples.utils.LdapTreeBuilder;
@@ -45,28 +45,28 @@ public class DefaultController {
}
@RequestMapping("/addPerson.do")
public ModelAndView addPerson() {
public String addPerson() {
Person person = getPerson();
personDao.create(person);
return showTree();
return "redirect:/showTree.do";
}
@RequestMapping("/updatePhoneNumber.do")
public ModelAndView updatePhoneNumber() {
public String updatePhoneNumber() {
Person person = personDao.findByPrimaryKey("Sweden", "company1", "John Doe");
person.setPhone(StringUtils.join(new String[] { person.getPhone(), "0" }));
personDao.update(person);
return showTree();
return "redirect:/showTree.do";
}
@RequestMapping("/removePerson.do")
public ModelAndView removePerson() {
public String removePerson() {
Person person = getPerson();
personDao.delete(person);
return showTree();
return "redirect:/showTree.do";
}
@RequestMapping("/showPerson.do")

View File

@@ -0,0 +1,3 @@
<body>
Plain example of Spring LDAP usage.
</body>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:/ldap.properties" />
<!--
This is for test and demo purposes only - the TestContextSourceFactoryBean starts an in-process
Apache Directory Server instance and populates it with data from the specified LDIF file.
A real-world application would use a DirContextSource instead.
-->
<bean id="contextSource"
class="org.springframework.ldap.test.TestContextSourceFactoryBean">
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
<property name="defaultPartitionName" value="jayway" />
<property name="principal" value="${userDn}" />
<property name="password" value="${password}" />
<property name="ldifFile" value="classpath:/setup_data.ldif" />
<property name="port" value="18880" />
</bean>
<!--
Below is an example of a ContextSource definition as it would look in a real application, connecting
against an external LDAP server.
<bean class="org.springframework.ldap.core.support.LdapContextSource" id="contextSource">
<property name="url" value="ldap://ldap.example.com" />
<property name="userDn" value="cn=admin,dc=261consulting,dc=com"/>
<property name="password" value="secret"/>
<property name="base" value="dc=261consulting,dc=com" />
</bean>
-->
<bean id="ldapTemplate"
class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="ldapTreeBuilder"
class="org.springframework.ldap.samples.utils.LdapTreeBuilder">
<constructor-arg ref="ldapTemplate" />
</bean>
<bean id="personDao"
class="org.springframework.ldap.samples.plain.dao.PersonDaoImpl">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
</beans>

Some files were not shown because too many files have changed in this diff Show More