Added article project that uses Spring 2.0 in order to verify backwards compatibility.

This commit is contained in:
Ulrik Sandberg
2009-01-28 20:03:02 +00:00
parent ef284530d0
commit 18397362a3
24 changed files with 1477 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
<?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

@@ -0,0 +1,189 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-parent</artifactId>
<version>1.3.0.CI-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-ldap-article-spring20</artifactId>
<name>Spring LDAP Article Sample (Spring 2.0)</name>
<packaging>war</packaging>
<description> Example code that matches the article published on
java.net on April 18, 2006. Uses Spring 2.0, rather than 2.5</description>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Spring Dependencies -->
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-test</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-samples-utils</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-dao</artifactId>
<version>2.0.8</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>2.0.8</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>2.0.8</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>2.0.8</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-support</artifactId>
<version>2.0.8</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.0.8</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-support</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>2.0.8</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,21 @@
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

@@ -0,0 +1,42 @@
/*
* Copyright 2005-2008 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

@@ -0,0 +1,163 @@
/*
* Copyright 2005-2008 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 javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.samples.article.domain.Person;
/**
* 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(DistinguishedName.EMPTY_PATH, 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(DistinguishedName.EMPTY_PATH, filter.encode(), getContextMapper());
}
/*
* @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String,
* java.lang.String)
*/
public Person findByPrimaryKey(String country, String company, String fullname) {
DistinguishedName dn = buildDn(country, company, fullname);
return (Person) ldapTemplate.lookup(dn, getContextMapper());
}
private ContextMapper getContextMapper() {
return new PersonContextMapper();
}
private DistinguishedName buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person.getFullName());
}
private DistinguishedName buildDn(String country, String company, String fullname) {
DistinguishedName dn = new DistinguishedName();
dn.add("c", country);
dn.add("ou", company);
dn.add("cn", fullname);
return dn;
}
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 the DistinguishedName.
*
*Mattias Hellborg Arthurssonellborg Arthursson
* @author Ulrik Sandberg
*/
private static class PersonContextMapper implements ContextMapper {
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter) ctx;
DistinguishedName dn = new DistinguishedName(context.getDn());
Person person = new Person();
person.setCountry(dn.getLdapRdn(0).getComponent().getValue());
person.setCompany(dn.getLdapRdn(1).getComponent().getValue());
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

@@ -0,0 +1,377 @@
/*
* Copyright 2005-2008 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

@@ -0,0 +1,104 @@
/*
* Copyright 2005-2008 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

@@ -0,0 +1,132 @@
package org.springframework.ldap.samples.article.web;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
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.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
/**
* 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(DistinguishedName.EMPTY_PATH);
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")) {
DistinguishedName distinguishedName = (DistinguishedName) node.getDn();
String country = encodeValue(distinguishedName.getValue("c"));
String company = encodeValue(distinguishedName.getValue("ou"));
String fullName = encodeValue(distinguishedName.getValue("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

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

View File

@@ -0,0 +1,7 @@
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

@@ -0,0 +1,36 @@
<?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="3900" />
</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

@@ -0,0 +1,35 @@
<?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

@@ -0,0 +1,20 @@
<%@ 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

@@ -0,0 +1,17 @@
<%@ 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

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

View File

@@ -0,0 +1,35 @@
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

@@ -0,0 +1,34 @@
<?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

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

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2005-2008 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

@@ -0,0 +1,33 @@
/*
* Copyright 2005-2008 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

@@ -0,0 +1,31 @@
/*
* Copyright 2005-2008 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

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

View File

@@ -0,0 +1,37 @@
<?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="3901" />
</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:3901" />
<property name="base" value="dc=jayway,dc=se" />
<property name="userDn" value="${userDn}" />
<property name="password" value="${password}" />
</bean>
</beans>

View File

@@ -16,6 +16,7 @@
<modules>
<module>samples-utils</module>
<module>article</module>
<module>article-spring20</module>
<module>demos</module>
</modules>
<repositories>