LDAP-266: Initial effort for automatic repository support.
This commit is contained in:
@@ -12,7 +12,8 @@ dependencies {
|
||||
compile "commons-logging:commons-logging:$commonsLoggingVersion",
|
||||
"org.springframework:spring-core:$springVersion",
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion"
|
||||
"org.springframework:spring-tx:$springVersion",
|
||||
"org.springframework.data:spring-data-commons:$springDataVersion"
|
||||
|
||||
provided "commons-pool:commons-pool:$commonsPoolVersion",
|
||||
"com.sun:ldapbp:1.0",
|
||||
|
||||
@@ -24,6 +24,7 @@ public abstract class Elements {
|
||||
public static final String POOLING = "pooling";
|
||||
public static final String LDAP_TEMPLATE = "ldap-template";
|
||||
public static final String TRANSACTION_MANAGER = "transaction-manager";
|
||||
public static final String REPOSITORIES = "repositories";
|
||||
public static final String DEFAULT_RENAMING_STRATEGY = "default-renaming-strategy";
|
||||
public static final String DIFFERENT_SUBTREE_RENAMING_STRATEGY = "different-subtree-renaming-strategy";
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.ldap.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
|
||||
import org.springframework.ldap.repository.config.LdapRepositoryConfigurationExtension;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
@@ -24,8 +26,12 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
public class LdapNamespaceHandler extends NamespaceHandlerSupport {
|
||||
@Override
|
||||
public void init() {
|
||||
LdapRepositoryConfigurationExtension extension = new LdapRepositoryConfigurationExtension();
|
||||
RepositoryBeanDefinitionParser repositoryParser = new RepositoryBeanDefinitionParser(extension);
|
||||
|
||||
registerBeanDefinitionParser(Elements.CONTEXT_SOURCE, new ContextSourceParser());
|
||||
registerBeanDefinitionParser(Elements.LDAP_TEMPLATE, new LdapTemplateParser());
|
||||
registerBeanDefinitionParser(Elements.TRANSACTION_MANAGER, new TransactionManagerParser());
|
||||
registerBeanDefinitionParser(Elements.REPOSITORIES, repositoryParser);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.ldap.ContextNotEmptyException;
|
||||
import org.springframework.ldap.NamingException;
|
||||
import org.springframework.ldap.core.support.AbstractContextSource;
|
||||
import org.springframework.ldap.filter.Filter;
|
||||
import org.springframework.ldap.odm.core.ObjectDirectoryMapper;
|
||||
import org.springframework.ldap.query.LdapQuery;
|
||||
import org.springframework.ldap.support.LdapUtils;
|
||||
|
||||
@@ -1620,6 +1621,22 @@ public interface LdapOperations {
|
||||
*/
|
||||
<T> T searchForObject(String base, String filter, ContextMapper<T> mapper);
|
||||
|
||||
/**
|
||||
* Perform a search with parameters from the specified LdapQuery. All found objects will be supplied to the
|
||||
* <code>NameClassPairCallbackHandler</code> for processing.
|
||||
*
|
||||
* @param query the LDAP query specification.
|
||||
* @param callbackHandler the <code>NameClassPairCallbackHandler</code> to supply all found entries to.
|
||||
* @return a <code>List</code> containing all entries received from the
|
||||
* <code>ContextMapper</code>.
|
||||
*
|
||||
* @throws NamingException if any error occurs.
|
||||
* @since 2.0
|
||||
* @see org.springframework.ldap.query.LdapQueryBuilder
|
||||
* @see org.springframework.ldap.core.support.CountNameClassPairCallbackHandler
|
||||
*/
|
||||
void search(LdapQuery query, NameClassPairCallbackHandler callbackHandler);
|
||||
|
||||
/**
|
||||
* Perform a search with parameters from the specified LdapQuery. All found objects will be supplied to the
|
||||
* <code>ContextMapper</code> for processing, and all returned objects will be collected in a list to be returned.
|
||||
@@ -1699,7 +1716,7 @@ public interface LdapOperations {
|
||||
* is set in the object, this will be used as the distinguished name of the new entry. If no explicit DN is specified,
|
||||
* an attempt will be made to calculate the name from fields annotated with {@link org.springframework.ldap.odm.annotations.DnAttribute}.
|
||||
*
|
||||
* @param entry The entry to be create, it must <em>not</em> already exist in the directory.
|
||||
* @param entry The entry to be create, it must <em>not</em> be null or already exist in the directory.
|
||||
*
|
||||
* @throws org.springframework.ldap.NamingException on error.
|
||||
* @throws IllegalArgumentException if the entry is null or on failure to determine the distinguished name.
|
||||
@@ -1825,4 +1842,12 @@ public interface LdapOperations {
|
||||
* @throws IncorrectResultSizeDataAccessException if more than one matching entry is found
|
||||
*/
|
||||
<T> T findOne(LdapQuery query, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Get the configured ObjectDirectoryMapper. For internal use.
|
||||
*
|
||||
* @return the configured ObjectDirectoryMapper.
|
||||
* @since 2.0
|
||||
*/
|
||||
ObjectDirectoryMapper getObjectDirectoryMapper();
|
||||
}
|
||||
|
||||
@@ -114,6 +114,11 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
|
||||
this.contextSource = contextSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectDirectoryMapper getObjectDirectoryMapper() {
|
||||
return odm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ObjectDirectoryMapper instance to use.
|
||||
*
|
||||
@@ -1669,6 +1674,15 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void search(LdapQuery query, NameClassPairCallbackHandler callbackHandler) {
|
||||
SearchControls searchControls = searchControlsForQuery(query, DONT_RETURN_OBJ_FLAG);
|
||||
search(query.base(),
|
||||
query.filter().encode(),
|
||||
searchControls,
|
||||
callbackHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> search(LdapQuery query, ContextMapper<T> mapper) {
|
||||
SearchControls searchControls = searchControlsForQuery(query, RETURN_OBJ_FLAG);
|
||||
|
||||
@@ -56,6 +56,15 @@ public interface ObjectDirectoryMapper {
|
||||
*/
|
||||
Name getId(Object entry);
|
||||
|
||||
/**
|
||||
* Set the distinguished name for the specified object.
|
||||
*
|
||||
* @param entry the entry to set the name on
|
||||
* @param id the name to set
|
||||
* @throws org.springframework.ldap.NamingException on error.
|
||||
*/
|
||||
void setId(Object entry, Name id);
|
||||
|
||||
Name getCalculatedId(Object entry);
|
||||
|
||||
/**
|
||||
|
||||
@@ -367,13 +367,27 @@ public class DefaultObjectDirectoryMapper implements ObjectDirectoryMapper {
|
||||
@Override
|
||||
public Name getId(Object entry) {
|
||||
try {
|
||||
return (Name)getEntityData(entry.getClass()).metaData.getIdAttribute().getField().get(entry);
|
||||
return (Name) getIdField(entry).get(entry);
|
||||
} catch (Exception e) {
|
||||
throw new InvalidEntryException(String.format("Can't get Id field from Entry %1$s", entry),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
private Field getIdField(Object entry) {
|
||||
return getEntityData(entry.getClass()).metaData.getIdAttribute().getField();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(Object entry, Name id) {
|
||||
try {
|
||||
getIdField(entry).set(entry, id);
|
||||
} catch (Exception e) {
|
||||
throw new InvalidEntryException(
|
||||
String.format("Can't set Id field on Entry %s to %s", entry, id), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name getCalculatedId(Object entry) {
|
||||
Assert.notNull(entry, "Entry must not be null");
|
||||
|
||||
@@ -157,9 +157,13 @@ public class LdapQueryBuilder implements LdapQuery {
|
||||
* @throws IllegalStateException if a filter has already been specified.
|
||||
*/
|
||||
public ConditionCriteria where(String attribute) {
|
||||
initRootContainer();
|
||||
return new DefaultConditionCriteria(rootContainer, attribute);
|
||||
}
|
||||
|
||||
private void initRootContainer() {
|
||||
assertFilterNotStarted();
|
||||
rootContainer = new DefaultContainerCriteria(this);
|
||||
return new DefaultConditionCriteria(rootContainer, attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,12 +178,17 @@ public class LdapQueryBuilder implements LdapQuery {
|
||||
* @throws IllegalStateException if a filter has already been specified.
|
||||
*/
|
||||
public LdapQuery filter(String hardcodedFilter) {
|
||||
assertFilterNotStarted();
|
||||
rootContainer = new DefaultContainerCriteria(this);
|
||||
initRootContainer();
|
||||
rootContainer.append(new HardcodedFilter(hardcodedFilter));
|
||||
return this;
|
||||
}
|
||||
|
||||
public LdapQuery filter(Filter filter) {
|
||||
initRootContainer();
|
||||
rootContainer.append(filter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a hardcoded filter using the specified parameters. The parameters will be properly encoded using
|
||||
* {@link LdapEncoder#filterEncode(String)} to make sure no malicious data gets through. The <code>filterFormat</code>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.repository;
|
||||
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
import org.springframework.ldap.core.LdapOperations;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class LdapRepositoryFactory extends RepositoryFactorySupport {
|
||||
private final LdapOperations ldapOperations;
|
||||
|
||||
public LdapRepositoryFactory(LdapOperations ldapOperations) {
|
||||
this.ldapOperations = ldapOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, ID extends Serializable> EntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected Object getTargetRepository(RepositoryMetadata metadata) {
|
||||
return new SimpleLdapRepository(
|
||||
ldapOperations,
|
||||
ldapOperations.getObjectDirectoryMapper(),
|
||||
metadata.getDomainType());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
return SimpleLdapRepository.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.springframework.ldap.repository;
|
||||
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
import org.springframework.ldap.core.LdapOperations;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.naming.Name;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class LdapRepositoryFactoryBean<T extends Repository<S, Name>, S> extends RepositoryFactoryBeanSupport<T, S, Name> {
|
||||
private LdapOperations ldapOperations;
|
||||
|
||||
public void setLdapOperations(LdapOperations ldapOperations) {
|
||||
this.ldapOperations = ldapOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryFactorySupport createRepositoryFactory() {
|
||||
return new LdapRepositoryFactory(ldapOperations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(ldapOperations, "LdapOperations must be set");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.repository;
|
||||
|
||||
import org.springframework.data.domain.Persistable;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.ldap.NameNotFoundException;
|
||||
import org.springframework.ldap.core.LdapOperations;
|
||||
import org.springframework.ldap.core.support.CountNameClassPairCallbackHandler;
|
||||
import org.springframework.ldap.filter.Filter;
|
||||
import org.springframework.ldap.odm.core.ObjectDirectoryMapper;
|
||||
import org.springframework.ldap.query.LdapQuery;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.naming.Name;
|
||||
import java.util.Iterator;
|
||||
|
||||
import static org.springframework.ldap.query.LdapQueryBuilder.query;
|
||||
|
||||
/**
|
||||
* Base repository implementation for LDAP.
|
||||
*
|
||||
* @author Mattias Hellborg Arthursson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SimpleLdapRepository<T> implements CrudRepository<T, Name> {
|
||||
private static final String OBJECTCLASS_ATTRIBUTE = "objectclass";
|
||||
private final LdapOperations ldapOperations;
|
||||
private final ObjectDirectoryMapper odm;
|
||||
private final Class<T> clazz;
|
||||
|
||||
public SimpleLdapRepository(LdapOperations ldapOperations, ObjectDirectoryMapper odm, Class<T> clazz) {
|
||||
this.ldapOperations = ldapOperations;
|
||||
this.odm = odm;
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
Filter filter = odm.filterFor(clazz, null);
|
||||
CountNameClassPairCallbackHandler callback = new CountNameClassPairCallbackHandler();
|
||||
LdapQuery query = query().attributes(OBJECTCLASS_ATTRIBUTE).filter(filter);
|
||||
ldapOperations.search(query, callback);
|
||||
|
||||
return callback.getNoOfRows();
|
||||
}
|
||||
|
||||
private <S extends T> boolean isNew(S entity, Name id) {
|
||||
if (entity instanceof Persistable) {
|
||||
Persistable persistable = (Persistable) entity;
|
||||
return persistable.isNew();
|
||||
} else {
|
||||
return id != null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> S save(S entity) {
|
||||
Assert.notNull(entity, "Entity must not be null");
|
||||
Name declaredId = odm.getId(entity);
|
||||
Name calculatedId = odm.getCalculatedId(entity);
|
||||
|
||||
if(isNew(entity, declaredId)) {
|
||||
if(declaredId == null) {
|
||||
odm.setId(entity, calculatedId);
|
||||
}
|
||||
|
||||
ldapOperations.create(entity);
|
||||
} else {
|
||||
ldapOperations.update(entity);
|
||||
if(declaredId != calculatedId) {
|
||||
odm.setId(entity, calculatedId);
|
||||
}
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> Iterable<S> save(Iterable<S> entities) {
|
||||
return new DelegatingIterable<S, S>(entities, new Function<S, S>() {
|
||||
@Override
|
||||
public S transform(S entry) {
|
||||
return save(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public T findOne(Name name) {
|
||||
Assert.notNull(name, "Id must not be null");
|
||||
try {
|
||||
return ldapOperations.findByDn(name, clazz);
|
||||
} catch (NameNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(Name name) {
|
||||
return findOne(name) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll() {
|
||||
return ldapOperations.findAll(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll(final Iterable<Name> names) {
|
||||
return new DelegatingIterable<Name, T>(names, new Function<Name, T>() {
|
||||
@Override
|
||||
public T transform(Name name) {
|
||||
return findOne(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Name name) {
|
||||
Assert.notNull(name, "Id must not be null");
|
||||
ldapOperations.unbind(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(T entity) {
|
||||
Assert.notNull(entity, "Entity must not be null");
|
||||
ldapOperations.delete(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Iterable<? extends T> entities) {
|
||||
for (T entity : entities) {
|
||||
delete(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
delete(findAll());
|
||||
}
|
||||
|
||||
private static class DelegatingIterable<F, T> implements Iterable<T> {
|
||||
private final Iterable<F> target;
|
||||
private final Function<F, T> function;
|
||||
|
||||
private DelegatingIterable(Iterable<F> target, Function<F, T> function) {
|
||||
this.target = target;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
final Iterator<F> targetIterator = target.iterator();
|
||||
return new Iterator<T>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return targetIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return function.transform(targetIterator.next());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Remove is not supported for this iterator");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private interface Function<F, T> {
|
||||
T transform(F entry);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.repository.config;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
|
||||
import org.springframework.data.repository.config.XmlRepositoryConfigurationSource;
|
||||
import org.springframework.ldap.repository.LdapRepositoryFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
public class LdapRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
|
||||
|
||||
private static final String ATT_LDAP_TEMPLATE_REF = "ldap-template-ref";
|
||||
|
||||
@Override
|
||||
protected String getModulePrefix() {
|
||||
return "ldap";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepositoryFactoryClassName() {
|
||||
return LdapRepositoryFactoryBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcess(BeanDefinitionBuilder builder, XmlRepositoryConfigurationSource config) {
|
||||
Element element = config.getElement();
|
||||
String ldapTemplateRef = element.getAttribute(ATT_LDAP_TEMPLATE_REF);
|
||||
if(!StringUtils.hasText(ldapTemplateRef)) {
|
||||
ldapTemplateRef = "ldapTemplate";
|
||||
}
|
||||
|
||||
builder.addPropertyReference("ldapOperations", ldapTemplateRef);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:ldap="http://www.springframework.org/schema/ldap"
|
||||
xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
elementFormDefault="qualified"
|
||||
targetNamespace="http://www.springframework.org/schema/ldap">
|
||||
|
||||
|
||||
<xs:import namespace="http://www.springframework.org/schema/data/repository"
|
||||
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" />
|
||||
|
||||
<xs:attributeGroup name="context-source.attlist">
|
||||
<xs:attribute name="id" type="xs:token">
|
||||
<xs:annotation>
|
||||
@@ -445,4 +449,20 @@
|
||||
<xs:attributeGroup ref="ldap:transaction-manager.attlist" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="repositories">
|
||||
<xs:complexType>
|
||||
<xs:complexContent>
|
||||
<xs:extension base="repository:repositories">
|
||||
<xs:attribute name="ldap-template-ref">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
The reference to an LdapTemplate. Will default to 'ldapTemplate'.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.springframework.ldap.config;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
public class DummyEntity {
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.config;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import javax.naming.Name;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
public interface DummyLdapRepository extends CrudRepository<DummyEntity, Name> {
|
||||
}
|
||||
@@ -305,4 +305,12 @@ public class LdapTemplateNamespaceHandlerTest {
|
||||
public void verifyParseWithPoolingAndNativePoolingWillFail() {
|
||||
new ClassPathXmlApplicationContext("/ldap-namespace-config-pooling-with-native.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyAutomaticRepositorySupport() {
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/ldap-namespace-config-with-repositories.xml");
|
||||
DummyLdapRepository repository = ctx.getBean(DummyLdapRepository.class);
|
||||
|
||||
assertNotNull(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?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:ldap="http://www.springframework.org/schema/ldap"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/ldap http://www.springframework.org/schema/ldap/spring-ldap.xsd">
|
||||
|
||||
<ldap:context-source password="apassword" url="ldap://localhost:389" username="uid=admin"/>
|
||||
<ldap:ldap-template />
|
||||
|
||||
<ldap:repositories base-package="org.springframework.ldap.config" />
|
||||
</beans>
|
||||
@@ -5,6 +5,7 @@ sourceCompatibility = '1.6'
|
||||
targetCompatibility = '1.6'
|
||||
|
||||
ext.springVersion = '3.2.4.RELEASE'
|
||||
ext.springDataVersion = '1.6.1.RELEASE'
|
||||
ext.springBatchVersion = '2.0.4.RELEASE'
|
||||
ext.junitVersion = '4.10'
|
||||
ext.commonsPoolVersion = '1.5.4'
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package org.springframework.ldap.itest.odm;
|
||||
|
||||
import org.springframework.data.domain.Persistable;
|
||||
import org.springframework.ldap.odm.annotations.Attribute;
|
||||
import org.springframework.ldap.odm.annotations.Entry;
|
||||
import org.springframework.ldap.odm.annotations.Id;
|
||||
import org.springframework.ldap.odm.annotations.Transient;
|
||||
|
||||
import javax.naming.Name;
|
||||
import java.util.List;
|
||||
@@ -11,7 +13,7 @@ import java.util.List;
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
@Entry(objectClasses = { "inetOrgPerson", "organizationalPerson", "person", "top" })
|
||||
public class Person {
|
||||
public class Person implements Persistable<Name> {
|
||||
@Id
|
||||
private Name dn;
|
||||
|
||||
@@ -30,6 +32,19 @@ public class Person {
|
||||
@Attribute(name = "telephoneNumber")
|
||||
private String telephoneNumber;
|
||||
|
||||
@Transient
|
||||
private boolean isNew;
|
||||
|
||||
@Override
|
||||
public Name getId() {
|
||||
return getDn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNew() {
|
||||
return isNew;
|
||||
}
|
||||
|
||||
public Name getDn() {
|
||||
return dn;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.itest.repositories;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.ldap.itest.odm.Person;
|
||||
|
||||
import javax.naming.Name;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
public interface PersonRepository extends CrudRepository<Person, Name> {
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.itest.repository;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
|
||||
import org.springframework.ldap.itest.odm.Person;
|
||||
import org.springframework.ldap.itest.repositories.PersonRepository;
|
||||
import org.springframework.ldap.odm.core.OdmException;
|
||||
import org.springframework.ldap.support.LdapNameBuilder;
|
||||
import org.springframework.ldap.support.LdapUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.ldap.query.LdapQueryBuilder.query;
|
||||
|
||||
/**
|
||||
* Tests for Spring LDAP automatic repository scan functionality.
|
||||
*
|
||||
* @author Ulrik Sandberg
|
||||
*/
|
||||
@ContextConfiguration(locations = {"/conf/repositoryScanTestContext.xml"})
|
||||
public class RepositoryScanITest extends AbstractLdapTemplateIntegrationTest {
|
||||
@Autowired
|
||||
private LdapTemplate ldapTemplate;
|
||||
|
||||
@Autowired
|
||||
private PersonRepository tested;
|
||||
|
||||
|
||||
@Test
|
||||
public void testFindOne() {
|
||||
Person person = tested.findOne(LdapUtils.newLdapName("cn=Some Person3, ou=Company1, c=Sweden"));
|
||||
|
||||
assertNotNull(person);
|
||||
Assert.assertEquals("Some Person3", person.getCommonName());
|
||||
Assert.assertEquals("Person3", person.getSurname());
|
||||
Assert.assertEquals("Sweden, Company1, Some Person3", person.getDesc().get(0));
|
||||
Assert.assertEquals("+46 555-123654", person.getTelephoneNumber());
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testFindByDn() {
|
||||
// Person person = tested.findByDn(LdapUtils.newLdapName("cn=Some Person3,ou=company1,c=Sweden"), Person.class);
|
||||
//
|
||||
// assertNotNull(person);
|
||||
// Assert.assertEquals("Some Person3", person.getCommonName());
|
||||
// Assert.assertEquals("Person3", person.getSurname());
|
||||
// Assert.assertEquals("Sweden, Company1, Some Person3", person.getDesc().get(0));
|
||||
// Assert.assertEquals("+46 555-123654", person.getTelephoneNumber());
|
||||
// }
|
||||
//
|
||||
// @Test(expected = OdmException.class)
|
||||
// public void testFindByDnThrowsExceptionOnInvalidEntry() {
|
||||
// tested.findByDn(LdapUtils.newLdapName("ou=company1,c=Sweden"), Person.class);
|
||||
// }
|
||||
//
|
||||
// @Test(expected = EmptyResultDataAccessException.class)
|
||||
// public void testFindOneThrowsEmptyResultIfNotFound() {
|
||||
// tested.findOne(query()
|
||||
// .where("cn").is("This cn does not exist"), Person.class);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testFind() {
|
||||
// List<Person> persons = tested.find(query()
|
||||
// .where("cn").is("Some Person3"), Person.class);
|
||||
//
|
||||
// Assert.assertEquals(1, persons.size());
|
||||
// Person person = persons.get(0);
|
||||
//
|
||||
// assertNotNull(person);
|
||||
// Assert.assertEquals("Some Person3", person.getCommonName());
|
||||
// Assert.assertEquals("Person3", person.getSurname());
|
||||
// Assert.assertEquals("Sweden, Company1, Some Person3", person.getDesc().get(0));
|
||||
// Assert.assertEquals("+46 555-123654", person.getTelephoneNumber());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testFindInCountry() {
|
||||
// List<Person> persons = tested.find(query()
|
||||
// .base("c=Sweden")
|
||||
// .where("cn").isPresent(), Person.class);
|
||||
//
|
||||
// Assert.assertEquals(4, persons.size());
|
||||
// Person person = persons.get(0);
|
||||
//
|
||||
// assertNotNull(person);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testFindAll() {
|
||||
// List<Person> result = tested.findAll(Person.class);
|
||||
// Assert.assertEquals(5, result.size());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testCreate() {
|
||||
// Person person = new Person();
|
||||
// person.setDn(LdapNameBuilder.newLdapName("ou=company1,c=Sweden")
|
||||
// .add("cn", "New Person").build());
|
||||
// person.setCommonName("New Person");
|
||||
// person.setSurname("Person");
|
||||
// person.setDesc(Arrays.asList("This is the description"));
|
||||
// person.setTelephoneNumber("0123456");
|
||||
//
|
||||
// tested.create(person);
|
||||
//
|
||||
// Assert.assertEquals(6, tested.findAll(Person.class).size());
|
||||
//
|
||||
// person = tested.findOne(query()
|
||||
// .where("cn").is("New Person"), Person.class);
|
||||
//
|
||||
// Assert.assertEquals("New Person", person.getCommonName());
|
||||
// Assert.assertEquals("Person", person.getSurname());
|
||||
// Assert.assertEquals("This is the description", person.getDesc().get(0));
|
||||
// Assert.assertEquals("0123456", person.getTelephoneNumber());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testUpdate() {
|
||||
// Person person = tested.findOne(query()
|
||||
// .where("cn").is("Some Person3"), Person.class);
|
||||
//
|
||||
// person.setDesc(Arrays.asList("New Description"));
|
||||
// tested.update(person);
|
||||
//
|
||||
// person = tested.findOne(query()
|
||||
// .where("cn").is("Some Person3"), Person.class);
|
||||
//
|
||||
// Assert.assertEquals("Some Person3", person.getCommonName());
|
||||
// Assert.assertEquals("Person3", person.getSurname());
|
||||
// Assert.assertEquals("New Description", person.getDesc().get(0));
|
||||
// Assert.assertEquals("+46 555-123654", person.getTelephoneNumber());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testDelete() {
|
||||
// Person person = tested.findOne(query()
|
||||
// .where("cn").is("Some Person3"), Person.class);
|
||||
//
|
||||
// tested.delete(person);
|
||||
//
|
||||
// try {
|
||||
// tested.findOne(query().where("cn").is("Some Person3"), Person.class);
|
||||
// fail("EmptyResultDataAccessException e");
|
||||
// } catch (EmptyResultDataAccessException e) {
|
||||
// Assert.assertTrue(true);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?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:ldap="http://www.springframework.org/schema/ldap"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/ldap http://www.springframework.org/schema/ldap/spring-ldap.xsd">
|
||||
<import resource="classpath:/conf/commonTestContext.xml" />
|
||||
|
||||
<ldap:context-source
|
||||
password="${password}"
|
||||
url="ldap://localhost:1888"
|
||||
username="${userDn}"
|
||||
base="dc=jayway,dc=se" />
|
||||
|
||||
<ldap:ldap-template />
|
||||
<ldap:repositories base-package="org.springframework.ldap.itest.repositories" />
|
||||
|
||||
<bean id="dummy" class="org.springframework.ldap.test.TestContextSourceFactoryBean">
|
||||
<property name="defaultPartitionSuffix" value="dc=jayway,dc=se" />
|
||||
<property name="defaultPartitionName" value="jayway" />
|
||||
<property name="ldifFile" value="classpath:/setup_data.ldif" />
|
||||
<property name="port" value="1888" />
|
||||
<property name="contextSource" ref="contextSource" />
|
||||
</bean>
|
||||
</beans>
|
||||
Reference in New Issue
Block a user