LDAP-267: Initial version of ldap namespace.

This commit is contained in:
Mattias Hellborg Arthursson
2013-10-07 15:48:09 +02:00
parent c80132adba
commit 0606f37388
21 changed files with 1339 additions and 1 deletions

View File

@@ -0,0 +1,165 @@
/*
* 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.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.pool.PoolExhaustedAction;
import org.springframework.ldap.pool.factory.PoolingContextSource;
import org.springframework.ldap.pool.validation.DefaultDirContextValidator;
import org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import static org.springframework.ldap.config.ParserUtils.NAMESPACE;
import static org.springframework.ldap.config.ParserUtils.getBoolean;
import static org.springframework.ldap.config.ParserUtils.getInt;
import static org.springframework.ldap.config.ParserUtils.getString;
/**
* @author Mattias Hellborg Arthursson
*/
public class ContextSourceParser implements BeanDefinitionParser {
private final static String ATT_ANONYMOUS_READ_ONLY = "anonymous-read-only";
private final static String ATT_AUTHENTICATION_STRATEGY_REF = "authentication-strategy-ref";
private final static String ATT_BASE = "base";
private final static String ATT_PASSWORD = "password";
private final static String ATT_NATIVE_POOLING = "native-pooling";
private final static String ATT_REFERRAL = "referral";
private final static String ATT_URL = "url";
// pooling attributes
private final static String ATT_MAX_ACTIVE = "max-active";
private final static String ATT_MAX_TOTAL = "max-total";
private final static String ATT_MAX_IDLE = "max-idle";
private final static String ATT_MIN_IDLE = "min-idle";
private final static String ATT_MAX_WAIT = "max-wait";
private final static String ATT_WHEN_EXHAUSTED = "when-exhausted";
private final static String ATT_TEST_ON_BORROW = "test-on-borrow";
private final static String ATT_TEST_ON_RETURN = "test-on-return";
private final static String ATT_TEST_WHILE_IDLE = "test-while-idle";
private final static String ATT_EVICTION_RUN_MILLIS = "eviction-run-interval-millis";
private final static String ATT_TESTS_PER_EVICTION_RUN = "tests-per-eviction-run";
private final static String ATT_EVICTABLE_TIME_MILLIS = "min-evictable-time-millis";
private final static String ATT_VALIDATION_QUERY_BASE = "validation-query-base";
private final static String ATT_VALIDATION_QUERY_FILTER = "validation-query-filter";
private final static String ATT_VALIDATION_QUERY_SEARCH_CONTROLS_REF = "validation-query-search-controls-ref";
private final static String ATT_USERNAME = "username";
static final String DEFAULT_ID = "contextSource";
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LdapContextSource.class);
String username = element.getAttribute(ATT_USERNAME);
String password = element.getAttribute(ATT_PASSWORD);
String url = element.getAttribute(ATT_URL);
Assert.hasText(username, "username attribute must be specified");
Assert.hasText(password, "password attribute must be specified");
Assert.hasText(url, "url attribute must be specified");
builder.addPropertyValue("userDn", username);
builder.addPropertyValue("password", password);
String[] urls = StringUtils.commaDelimitedListToStringArray(url);
builder.addPropertyValue("urls", urls);
builder.addPropertyValue("base", getString(element, ATT_BASE, ""));
builder.addPropertyValue("referral", getString(element, ATT_REFERRAL, null));
builder.addPropertyValue("anonymousReadOnly", getBoolean(element, ATT_ANONYMOUS_READ_ONLY, false));
builder.addPropertyValue("pooled", getBoolean(element, ATT_NATIVE_POOLING, false));
String authStrategyRef = element.getAttribute(ATT_AUTHENTICATION_STRATEGY_REF);
if(StringUtils.hasText(authStrategyRef)) {
builder.addPropertyReference("authenticationStrategy", authStrategyRef);
}
BeanDefinition targetContextSourceDefinition = builder.getBeanDefinition();
targetContextSourceDefinition = applyPoolingIfApplicable(targetContextSourceDefinition, element);
BeanDefinitionBuilder proxyBuilder = BeanDefinitionBuilder.rootBeanDefinition(TransactionAwareContextSourceProxy.class);
proxyBuilder.addConstructorArgValue(targetContextSourceDefinition);
AbstractBeanDefinition proxyBeanDefinition = proxyBuilder.getBeanDefinition();
String id = getString(element, AbstractBeanDefinitionParser.ID_ATTRIBUTE, DEFAULT_ID);
parserContext.registerBeanComponent(new BeanComponentDefinition(proxyBeanDefinition, id));
return proxyBeanDefinition;
}
private BeanDefinition applyPoolingIfApplicable(BeanDefinition targetContextSourceDefinition, Element element) {
NodeList poolingChildren = element.getElementsByTagNameNS(NAMESPACE, Elements.POOLING);
if(poolingChildren.getLength() == 0) {
return targetContextSourceDefinition;
}
Element poolingElement = (Element) poolingChildren.item(0);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(PoolingContextSource.class);
builder.addPropertyValue("contextSource", targetContextSourceDefinition);
builder.addPropertyValue("maxActive", getInt(poolingElement, ATT_MAX_ACTIVE, 8));
builder.addPropertyValue("maxTotal", getInt(poolingElement, ATT_MAX_TOTAL, -1));
builder.addPropertyValue("maxIdle", getInt(poolingElement, ATT_MAX_IDLE, 8));
builder.addPropertyValue("minIdle", getInt(poolingElement, ATT_MIN_IDLE, 0));
builder.addPropertyValue("maxWait", getInt(poolingElement, ATT_MAX_WAIT, -1));
String whenExhausted = getString(poolingElement, ATT_WHEN_EXHAUSTED, PoolExhaustedAction.BLOCK.name());
builder.addPropertyValue("whenExhaustedAction", PoolExhaustedAction.valueOf(whenExhausted).getValue());
boolean testOnBorrow = getBoolean(poolingElement, ATT_TEST_ON_BORROW, false);
boolean testOnReturn = getBoolean(poolingElement, ATT_TEST_ON_RETURN, false);
boolean testWhileIdle = getBoolean(poolingElement, ATT_TEST_WHILE_IDLE, false);
if(testOnBorrow || testOnReturn || testWhileIdle) {
populatePoolValidationProperties(builder, poolingElement, testOnBorrow, testOnReturn, testWhileIdle);
}
return builder.getBeanDefinition();
}
private void populatePoolValidationProperties(BeanDefinitionBuilder builder, Element element,
boolean testOnBorrow, boolean testOnReturn, boolean testWhileIdle) {
builder.addPropertyValue("testOnBorrow", testOnBorrow);
builder.addPropertyValue("testOnReturn", testOnReturn);
builder.addPropertyValue("testWhileIdle", testWhileIdle);
BeanDefinitionBuilder validatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultDirContextValidator.class);
validatorBuilder.addPropertyValue("base", getString(element, ATT_VALIDATION_QUERY_BASE, ""));
validatorBuilder.addPropertyValue("filter",
getString(element, ATT_VALIDATION_QUERY_FILTER, DefaultDirContextValidator.DEFAULT_FILTER));
String searchControlsRef = element.getAttribute(ATT_VALIDATION_QUERY_SEARCH_CONTROLS_REF);
if(StringUtils.hasText(searchControlsRef)) {
validatorBuilder.addPropertyReference("searchControls", searchControlsRef);
}
builder.addPropertyValue("dirContextValidator", validatorBuilder.getBeanDefinition());
builder.addPropertyValue("timeBetweenEvictionRunsMillis", getInt(element, ATT_EVICTION_RUN_MILLIS, -1));
builder.addPropertyValue("numTestsPerEvictionRun", getInt(element, ATT_TESTS_PER_EVICTION_RUN, 3));
builder.addPropertyValue("minEvictableIdleTimeMillis", getInt(element, ATT_EVICTABLE_TIME_MILLIS, 1000 * 60 * 30));
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.ldap.transaction.compensating.support.DefaultTempEntryRenamingStrategy;
import org.w3c.dom.Element;
import static org.springframework.ldap.config.ParserUtils.getString;
/**
* @author Mattias Hellborg Arthursson
*/
public class DefaultRenamingStrategyParser implements BeanDefinitionParser {
private final static String ATT_TEMP_SUFFIX = "temp-suffix";
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DefaultTempEntryRenamingStrategy.class);
builder.addPropertyValue("tempSuffix",
getString(element, ATT_TEMP_SUFFIX,
DefaultTempEntryRenamingStrategy.DEFAULT_TEMP_SUFFIX));
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
parserContext.getContainingBeanDefinition().getPropertyValues()
.addPropertyValue("renamingStrategy", beanDefinition);
return beanDefinition;
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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;
/**
* @author Mattias Hellborg Arthursson
*/
public abstract class Elements {
public static final String CONTEXT_SOURCE = "context-source";
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 DEFAULT_RENAMING_STRATEGY = "default-renaming-strategy";
public static final String DIFFERENT_SUBTREE_RENAMING_STRATEGY = "different-subtree-renaming-strategy";
}

View File

@@ -0,0 +1,31 @@
/*
* 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.beans.factory.xml.NamespaceHandlerSupport;
/**
* @author Mattias Hellborg Arthursson
*/
public class LdapNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser(Elements.CONTEXT_SOURCE, new ContextSourceParser());
registerBeanDefinitionParser(Elements.LDAP_TEMPLATE, new LdapTemplateParser());
registerBeanDefinitionParser(Elements.TRANSACTION_MANAGER, new TransactionManagerParser());
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.query.SearchScope;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import static org.springframework.ldap.config.ParserUtils.getBoolean;
import static org.springframework.ldap.config.ParserUtils.getInt;
import static org.springframework.ldap.config.ParserUtils.getString;
/**
* @author Mattias Hellborg Arthursson
*/
public class LdapTemplateParser implements BeanDefinitionParser {
private final static String ATT_COUNT_LIMIT = "count-limit";
private final static String ATT_TIME_LIMIT = "time-limit";
private final static String ATT_SEARCH_SCOPE = "search-scope";
private final static String ATT_IGNORE_PARTIAL_RESULT = "ignore-partial-result";
private final static String ATT_IGNORE_NAME_NOT_FOUND = "ignore-name-not-found";
private final static String ATT_ODM_REF = "odm-ref";
private final static String ATT_CONTEXT_SOURCE_REF = "context-source-ref";
private final static String DEFAULT_ID = "ldapTemplate";
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LdapTemplate.class);
String contextSourceRef = getString(element, ATT_CONTEXT_SOURCE_REF, ContextSourceParser.DEFAULT_ID);
builder.addPropertyReference("contextSource", contextSourceRef);
builder.addPropertyValue("defaultCountLimit", getInt(element, ATT_COUNT_LIMIT, 0));
builder.addPropertyValue("defaultTimeLimit", getInt(element, ATT_TIME_LIMIT, 0));
String searchScope = getString(element, ATT_SEARCH_SCOPE, SearchScope.SUBTREE.toString());
builder.addPropertyValue("defaultSearchScope", SearchScope.valueOf(searchScope).getId());
builder.addPropertyValue("ignorePartialResultException", getBoolean(element, ATT_IGNORE_PARTIAL_RESULT, false));
builder.addPropertyValue("ignoreNameNotFoundException", getBoolean(element, ATT_IGNORE_NAME_NOT_FOUND, false));
String odmRef = element.getAttribute(ATT_ODM_REF);
if(StringUtils.hasText(odmRef)) {
builder.addPropertyReference("objectDirectoryMapper", odmRef);
}
String id = getString(element, AbstractBeanDefinitionParser.ID_ATTRIBUTE, DEFAULT_ID);
BeanDefinition beanDefinition = builder.getBeanDefinition();
parserContext.registerBeanComponent(new BeanComponentDefinition(beanDefinition, id));
return beanDefinition;
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.util.StringUtils;
import org.w3c.dom.Element;
/**
* @author Mattias Hellborg Arthursson
*/
class ParserUtils {
static final String NAMESPACE = "http://www.springframework.org/schema/ldap";
/**
* Not to be instantiated
*/
private ParserUtils() {
}
static boolean getBoolean(Element element, String attribute, boolean defaultValue) {
String theValue = element.getAttribute(attribute);
if (StringUtils.hasText(theValue)) {
return Boolean.valueOf(theValue);
}
return defaultValue;
}
static String getString(Element element, String attribute, String defaultValue) {
String theValue = element.getAttribute(attribute);
if (StringUtils.hasText(theValue)) {
return theValue;
}
return defaultValue;
}
static int getInt(Element element, String attribute, int defaultValue) {
String theValue = element.getAttribute(attribute);
if (StringUtils.hasText(theValue)) {
return Integer.parseInt(theValue);
}
return defaultValue;
}
}

View File

@@ -0,0 +1,107 @@
/*
* 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.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManager;
import org.springframework.ldap.transaction.compensating.support.DefaultTempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.support.DifferentSubtreeTempEntryRenamingStrategy;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import static org.springframework.ldap.config.ParserUtils.NAMESPACE;
import static org.springframework.ldap.config.ParserUtils.getString;
/**
* @author Mattias Hellborg Arthursson
*/
public class TransactionManagerParser implements BeanDefinitionParser {
private final static String ATT_CONTEXT_SOURCE_REF = "context-source-ref";
private final static String ATT_DATA_SOURCE_REF = "data-source-ref";
private final static String ATT_SESSION_FACTORY_REF = "session-factory-ref";
private final static String ATT_TEMP_SUFFIX = "temp-suffix";
private final static String ATT_SUBTREE_NODE = "subtree-node";
private final static String DEFAULT_ID = "transactionManager";
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
String contextSourceRef = getString(element, ATT_CONTEXT_SOURCE_REF, ContextSourceParser.DEFAULT_ID);
String dataSourceRef = element.getAttribute(ATT_DATA_SOURCE_REF);
String sessionFactoryRef = element.getAttribute(ATT_SESSION_FACTORY_REF);
if(StringUtils.hasText(dataSourceRef) && StringUtils.hasText(sessionFactoryRef)) {
throw new IllegalArgumentException(
String.format("Only one of %s and %s can be specified",
ATT_DATA_SOURCE_REF, ATT_SESSION_FACTORY_REF));
}
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ContextSourceTransactionManager.class);
builder.addPropertyReference("contextSource", contextSourceRef);
NodeList defaultStrategyChildren =
element.getElementsByTagNameNS(NAMESPACE, Elements.DEFAULT_RENAMING_STRATEGY);
NodeList differentSubtreeChildren =
element.getElementsByTagNameNS(NAMESPACE, Elements.DIFFERENT_SUBTREE_RENAMING_STRATEGY);
if(defaultStrategyChildren.getLength() == 1) {
builder.addPropertyValue("renamingStrategy", parseDefaultRenamingStrategy((Element) defaultStrategyChildren.item(0)));
}
if(differentSubtreeChildren.getLength() == 1) {
builder.addPropertyValue("renamingStrategy", parseDifferentSubtreeRenamingStrategy((Element) differentSubtreeChildren.item(0)));
}
String id = getString(element, AbstractBeanDefinitionParser.ID_ATTRIBUTE, DEFAULT_ID);
BeanDefinition beanDefinition = builder.getBeanDefinition();
parserContext.registerBeanComponent(new BeanComponentDefinition(beanDefinition, id));
return beanDefinition;
}
private BeanDefinition parseDifferentSubtreeRenamingStrategy(Element element) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DifferentSubtreeTempEntryRenamingStrategy.class);
String subtreeNode = element.getAttribute(ATT_SUBTREE_NODE);
Assert.hasText(subtreeNode, ATT_SUBTREE_NODE + " must be specified");
builder.addConstructorArgValue(subtreeNode);
return builder.getBeanDefinition();
}
public BeanDefinition parseDefaultRenamingStrategy(Element element) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DefaultTempEntryRenamingStrategy.class);
builder.addPropertyValue("tempSuffix",
getString(element, ATT_TEMP_SUFFIX,
DefaultTempEntryRenamingStrategy.DEFAULT_TEMP_SUFFIX));
return builder.getBeanDefinition();
}
}

View File

@@ -0,0 +1,20 @@
package org.springframework.ldap.pool;
/**
* @author Mattias Hellborg Arthursson
*/
public enum PoolExhaustedAction {
FAIL((byte)0),
BLOCK((byte)1),
GROW((byte)2);
private final byte value;
private PoolExhaustedAction(byte value) {
this.value = value;
}
public byte getValue() {
return value;
}
}

View File

@@ -74,6 +74,8 @@ import javax.naming.directory.SearchResult;
* @author Eric Dalquist
*/
public class DefaultDirContextValidator implements DirContextValidator {
public static final String DEFAULT_FILTER = "objectclass=*";
/**
* Logger for this class and sub-classes
*/
@@ -107,7 +109,7 @@ public class DefaultDirContextValidator implements DirContextValidator {
this.base = "";
this.filter = "objectclass=*";
this.filter = DEFAULT_FILTER;
}
/**

View File

@@ -0,0 +1 @@
http\://www.springframework.org/schema/ldap=org.springframework.ldap.config.LdapNamespaceHandler

View File

@@ -0,0 +1,2 @@
http\://www.springframework.org/schema/ldap/spring-ldap.xsd=org/springframework/ldap/config/spring-ldap-2.0.xsd
http\://www.springframework.org/schema/ldap/spring-ldap-2.0.xsd=org/springframework/ldap/config/spring-ldap-2.0.xsd

View File

@@ -0,0 +1,432 @@
<?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"
elementFormDefault="qualified"
targetNamespace="http://www.springframework.org/schema/ldap">
<xs:attributeGroup name="context-source.attlist">
<xs:attribute name="id" type="xs:token">
<xs:annotation>
<xs:documentation>
A bean identifier, used for referring to the bean elsewhere in the context.
&quot;contextSource&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="anonymous-read-only" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Defines whether read-only operations will be performed using an anonymous (unauthenticated) context.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="authentication-source-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the AuthenticationSource instance to use. If not specified, a SimpleAuthenticationSource will
be used.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="authentication-strategy-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the DirContextAuthenticationStrategy instance to use. If not specified, a SimpleDirContextAuthenticationStrategy
will be used.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="base" type="xs:string">
<xs:annotation>
<xs:documentation>
The base DN. If specified, all LDAP operations on contexts retrieved from this ContextSource will
be relative to this DN. Default is an empty distinguished name (i.e. all operations will be
relative to the directory root).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="password" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>
The password to use for authentication.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="native-pooling" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Specify whether native Java LDAP connection pooling should be used. Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="referral">
<xs:annotation>
<xs:documentation>
Defines the strategy to handle referrals, as described on http://docs.oracle.com/javase/jndi/tutorial/ldap/referral/jndi.html.
Default is null.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="ignore" />
<xs:enumeration value="follow" />
<xs:enumeration value="throw" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="url" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>
URL of the LDAP server to use. If fail-over functionality is desired, more than one URL can
be specified, separated using comma (,).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="username" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>
The username (principal) to use for authentication. This will normally be the distinguished name
of an admin user.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="pooling.attlist">
<xs:attribute name="max-active" type="xs:integer">
<xs:annotation>
<xs:documentation>
The maximum number of active connections of each type (read-only|read-write)
that can be allocated from the pool at the same time, or non-positive for no limit.
Default is 8.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max-total" type="xs:integer">
<xs:annotation>
<xs:documentation>
The overall maximum number of active connections (for all types) that can be allocated from
this pool at the same time, or non-positive for no limit. Default is -1 (no limit).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max-idle" type="xs:integer">
<xs:annotation>
<xs:documentation>
The maximum number of active connections of each type (read-only|read-write) that can remain idle in the pool,
without extra ones being released, or non-positive for no limit. Default is 8.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min-idle" type="xs:integer">
<xs:annotation>
<xs:documentation>
The minimum number of active connections of each type (read-only|read-write) that can remain
idle in the pool, without extra ones being created, or zero to create none. Default is 0.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max-wait" type="xs:integer">
<xs:annotation>
<xs:documentation>
The maximum number of milliseconds that the pool will wait (when there are no available connections)
for a connection to be returned before throwing an exception, or non-positive to wait indefinitely.
Default is -1.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="when-exhausted">
<xs:annotation>
<xs:documentation>
Specifies the behaviour when the pool is exhausted.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="FAIL">
<xs:annotation>
<xs:documentation>
Throw a NoSuchElementException when the pool is exhausted
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="BLOCK">
<xs:annotation>
<xs:documentation>
Wait until a new object is available. If max-wait is positive a NoSuchElementException
is thrown if no new object is available after the maxWait time expires.
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="GROW">
<xs:annotation>
<xs:documentation>
Create and return a new object (essentially making maxActive meaningless).
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="test-on-borrow" type="xs:boolean">
<xs:annotation>
<xs:documentation>
The indication of whether objects will be validated before being borrowed from the pool.
If the object fails to validate, it will be dropped from the pool, and an attempt to borrow another will be made.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="test-on-return" type="xs:boolean">
<xs:annotation>
<xs:documentation>
The indication of whether objects will be validated before being returned to the pool.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="test-while-idle" type="xs:boolean">
<xs:annotation>
<xs:documentation>
The indication of whether objects will be validated by the idle object evictor (if any).
If an object fails to validate, it will be dropped from the pool.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="eviction-run-interval-millis" type="xs:int">
<xs:annotation>
<xs:documentation>
The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive,
no idle object evictor thread will be run. Default is -1.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="tests-per-eviction-run" type="xs:int">
<xs:annotation>
<xs:documentation>
The number of objects to examine during each run of the idle object evictor thread (if any).
Default is 3.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min-evictable-time-millis" type="xs:int">
<xs:annotation>
<xs:documentation>
The minimum amount of time an object may sit idle in the pool before it is eligible
for eviction by the idle object evictor (if any). Default is 1000 * 60 * 30.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="validation-query-base" type="xs:string">
<xs:annotation>
<xs:documentation>
The base dn to use for validation searches. Default is LdapUtils.emptyPath().
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="validation-query-filter" type="xs:string">
<xs:annotation>
<xs:documentation>
The filter to use for validation queries. Default is (objectclass=*).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="validation-query-search-controls-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the SearchControls instance to use for searches. Default is searchScope=OBJECT_SCOPE;
countLimit: 1; timeLimit: 500; returningAttributes: [objectclass].
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="context-source">
<xs:annotation>
<xs:documentation>
Creates a ContextSource instance to be used to get LdapContexts for communicating with an LDAP server.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element name="pooling">
<xs:annotation>
<xs:documentation>
Defines the settings to use for the Spring LDAP connection pooling support.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attributeGroup ref="ldap:pooling.attlist" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attributeGroup ref="ldap:context-source.attlist" />
</xs:complexType>
</xs:element>
<xs:attributeGroup name="ldap-template.attlist">
<xs:attribute name="id" type="xs:token">
<xs:annotation>
<xs:documentation>
A bean identifier, used for referring to the bean elsewhere in the context.
Default is &quot;ldapTemplate&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="context-source-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the ContextSource instance to use. Default is &quot;contextSource&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="count-limit" type="xs:integer">
<xs:annotation>
<xs:documentation>
The default count limit for searches. Default is 0 (no limit).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="time-limit" type="xs:integer">
<xs:annotation>
<xs:documentation>
The default time limit for searches. Default is 0 (no limit).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="search-scope">
<xs:annotation>
<xs:documentation>
The default search scope for searches. Default is SUBTREE.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="OBJECT" />
<xs:enumeration value="ONELEVEL" />
<xs:enumeration value="SUBTREE" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="ignore-name-not-found" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Specifies whether NameNotFoundException should be ignored in searches. Setting this
attribute to true will cause errors caused by invalid search base to be silently swallowed.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ignore-partial-result" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Specifies whether PartialResultException should be ignored in searches. Some LDAP servers
have problems with referrals; these should normally be followed automatically, but if this
doesn't work it will manifest itself with a PartialResultException. Setting this attribute
to true presents a work-around to this problem. Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="odm-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the ObjectDirectoryMapper instance to use. Default is a default-configured DefaultObjectDirectoryMapper.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="ldap-template">
<xs:annotation>
<xs:documentation>
Creates an LdapTemplate instance.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attributeGroup ref="ldap:ldap-template.attlist" />
</xs:complexType>
</xs:element>
<xs:attributeGroup name="transaction-manager.attlist">
<xs:attribute name="id" type="xs:string">
<xs:annotation>
<xs:documentation>
Id of this instance. Default is &quot;transactionManager&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="context-source-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the ContextSource instance to use. &quot;contextSource&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="data-source-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the DataSource instance to use.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="session-factory-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the Hibernate SessionFactory instance to use.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="transaction-manager">
<xs:annotation>
<xs:documentation>
Creates an ContextSourceTransactionManager. If data-source-ref or session-factory-ref is specified,
a DataSourceAndContextSourceTransactionManager/HibernateAndContextSourceTransactionManager will be
created.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:choice minOccurs="1" maxOccurs="1">
<xs:element name="default-renaming-strategy">
<xs:annotation>
<xs:documentation>
The default (simplistic) TempEntryRenamingStrategy. Please note that this
strategy will not work for more advanced scenarios. See reference documentation
for details.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="temp-suffix" type="xs:string">
<xs:annotation>
<xs:documentation>
The default suffix that will be added to modified entries.
Default is &quot;_temp&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="different-subtree-renaming-strategy">
<xs:annotation>
<xs:documentation>
TempEntryRenamingStrategy that moves the entry to a different subtree than
the original entry.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="subtree-node" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>
The subtree base where changed entries should be moved.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:choice>
<xs:attributeGroup ref="ldap:transaction-manager.attlist" />
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -0,0 +1,234 @@
/*
* 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.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.DirContextAuthenticationStrategy;
import org.springframework.ldap.pool.factory.PoolingContextSource;
import org.springframework.ldap.pool.validation.DefaultDirContextValidator;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManager;
import org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy;
import org.springframework.ldap.transaction.compensating.support.DefaultTempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.support.DifferentSubtreeTempEntryRenamingStrategy;
import org.springframework.transaction.PlatformTransactionManager;
import javax.naming.directory.SearchControls;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.internal.util.reflection.Whitebox.getInternalState;
/**
* @author Mattias Hellborg Arthursson
*/
public class LdapTemplateNamespaceHandlerTest {
@Test
public void verifyParseWithDefaultValues() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/ldap-namespace-config-defaults.xml");
ContextSource outerContextSource = ctx.getBean(ContextSource.class);
LdapTemplate ldapTemplate = ctx.getBean(LdapTemplate.class);
assertNotNull(outerContextSource);
assertNotNull(ldapTemplate);
assertTrue(outerContextSource instanceof TransactionAwareContextSourceProxy);
ContextSource contextSource = ((TransactionAwareContextSourceProxy) outerContextSource).getTarget();
assertEquals(LdapUtils.emptyLdapName(), getInternalState(contextSource, "base"));
assertEquals("uid=admin", getInternalState(contextSource, "userDn"));
assertEquals("apassword", getInternalState(contextSource, "password"));
assertArrayEquals(new String[]{"ldap://localhost:389"}, (Object[]) getInternalState(contextSource, "urls"));
assertEquals(Boolean.FALSE, getInternalState(contextSource, "pooled"));
assertEquals(Boolean.FALSE, getInternalState(contextSource, "anonymousReadOnly"));
assertNull(getInternalState(contextSource, "referral"));
assertSame(outerContextSource, getInternalState(ldapTemplate, "contextSource"));
assertEquals(Boolean.FALSE, getInternalState(ldapTemplate, "ignorePartialResultException"));
assertEquals(Boolean.FALSE, getInternalState(ldapTemplate, "ignoreNameNotFoundException"));
assertEquals(0, getInternalState(ldapTemplate, "defaultCountLimit"));
assertEquals(0, getInternalState(ldapTemplate, "defaultTimeLimit"));
assertEquals(SearchControls.SUBTREE_SCOPE, getInternalState(ldapTemplate, "defaultSearchScope"));
}
@Test
public void verifyParseWithCustomValues() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/ldap-namespace-config-values.xml");
ContextSource outerContextSource = ctx.getBean(ContextSource.class);
LdapTemplate ldapTemplate = ctx.getBean(LdapTemplate.class);
DirContextAuthenticationStrategy authenticationStrategy = ctx.getBean(DirContextAuthenticationStrategy.class);
assertNotNull(outerContextSource);
assertNotNull(ldapTemplate);
assertTrue(outerContextSource instanceof TransactionAwareContextSourceProxy);
ContextSource contextSource = ((TransactionAwareContextSourceProxy) outerContextSource).getTarget();
assertEquals(LdapUtils.newLdapName("dc=261consulting,dc=com"), getInternalState(contextSource, "base"));
assertEquals("uid=admin", getInternalState(contextSource, "userDn"));
assertEquals("apassword", getInternalState(contextSource, "password"));
assertArrayEquals(new String[]{"ldap://localhost:389"}, (Object[]) getInternalState(contextSource, "urls"));
assertEquals(Boolean.TRUE, getInternalState(contextSource, "pooled"));
assertEquals(Boolean.TRUE, getInternalState(contextSource, "anonymousReadOnly"));
assertEquals("follow", getInternalState(contextSource, "referral"));
assertSame(authenticationStrategy, getInternalState(contextSource, "authenticationStrategy"));
assertSame(outerContextSource, getInternalState(ldapTemplate, "contextSource"));
assertEquals(Boolean.TRUE, getInternalState(ldapTemplate, "ignorePartialResultException"));
assertEquals(Boolean.TRUE, getInternalState(ldapTemplate, "ignoreNameNotFoundException"));
assertEquals(100, getInternalState(ldapTemplate, "defaultCountLimit"));
assertEquals(200, getInternalState(ldapTemplate, "defaultTimeLimit"));
assertEquals(SearchControls.OBJECT_SCOPE, getInternalState(ldapTemplate, "defaultSearchScope"));
}
@Test
public void verifyParseWithDefaultTransactions() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/ldap-namespace-config-transactional-defaults.xml");
ContextSource outerContextSource = ctx.getBean(ContextSource.class);
PlatformTransactionManager transactionManager = ctx.getBean(PlatformTransactionManager.class);
assertNotNull(outerContextSource);
assertNotNull(transactionManager);
assertTrue(outerContextSource instanceof TransactionAwareContextSourceProxy);
ContextSource contextSource = ((TransactionAwareContextSourceProxy) outerContextSource).getTarget();
assertTrue(transactionManager instanceof ContextSourceTransactionManager);
Object delegate = getInternalState(transactionManager, "delegate");
assertSame(contextSource, getInternalState(delegate, "contextSource"));
TempEntryRenamingStrategy renamingStrategy =
(TempEntryRenamingStrategy) getInternalState(delegate, "renamingStrategy");
assertTrue(renamingStrategy instanceof DefaultTempEntryRenamingStrategy);
assertEquals("_temp", getInternalState(renamingStrategy, "tempSuffix"));
}
@Test
public void verifyParseTransactionsWithDefaultStrategyAndSuffix() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/ldap-namespace-config-transactional-defaults-with-suffix.xml");
PlatformTransactionManager transactionManager = ctx.getBean(PlatformTransactionManager.class);
assertNotNull(transactionManager);
assertTrue(transactionManager instanceof ContextSourceTransactionManager);
Object delegate = getInternalState(transactionManager, "delegate");
TempEntryRenamingStrategy renamingStrategy =
(TempEntryRenamingStrategy) getInternalState(delegate, "renamingStrategy");
assertTrue(renamingStrategy instanceof DefaultTempEntryRenamingStrategy);
assertEquals("_thisisthesuffix", getInternalState(renamingStrategy, "tempSuffix"));
}
@Test
public void verifyParseTransactionsWithDifferentSubtreeStrategy() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/ldap-namespace-config-transactional-different-subtree.xml");
PlatformTransactionManager transactionManager = ctx.getBean(PlatformTransactionManager.class);
assertNotNull(transactionManager);
assertTrue(transactionManager instanceof ContextSourceTransactionManager);
Object delegate = getInternalState(transactionManager, "delegate");
TempEntryRenamingStrategy renamingStrategy =
(TempEntryRenamingStrategy) getInternalState(delegate, "renamingStrategy");
assertTrue(renamingStrategy instanceof DifferentSubtreeTempEntryRenamingStrategy);
assertEquals(LdapUtils.newLdapName("ou=temp"), getInternalState(renamingStrategy, "subtreeNode"));
}
@Test
public void verifyParsePoolingDefaults() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/ldap-namespace-config-pooling-defaults.xml");
ContextSource outerContextSource = ctx.getBean(ContextSource.class);
assertNotNull(outerContextSource);
assertTrue(outerContextSource instanceof TransactionAwareContextSourceProxy);
ContextSource pooledContextSource = ((TransactionAwareContextSourceProxy) outerContextSource).getTarget();
assertNotNull(pooledContextSource);
assertTrue(pooledContextSource instanceof PoolingContextSource);
Object objectFactory = getInternalState(pooledContextSource, "dirContextPoolableObjectFactory");
assertNotNull(getInternalState(objectFactory, "contextSource"));
assertNull(getInternalState(objectFactory, "dirContextValidator"));
GenericKeyedObjectPool objectPool = (GenericKeyedObjectPool) getInternalState(pooledContextSource, "keyedObjectPool");
assertEquals(8, objectPool.getMaxActive());
assertEquals(-1, objectPool.getMaxTotal());
assertEquals(8, objectPool.getMaxIdle());
assertEquals(-1, objectPool.getMaxWait());
assertEquals(0, objectPool.getMinIdle());
assertEquals(1, objectPool.getWhenExhaustedAction());
}
@Test
public void verifyParsePoolingSizeSet() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/ldap-namespace-config-pooling-configured-poolsize.xml");
ContextSource outerContextSource = ctx.getBean(ContextSource.class);
assertNotNull(outerContextSource);
ContextSource pooledContextSource = ((TransactionAwareContextSourceProxy) outerContextSource).getTarget();
assertNotNull(pooledContextSource);
GenericKeyedObjectPool objectPool = (GenericKeyedObjectPool) getInternalState(pooledContextSource, "keyedObjectPool");
assertEquals(10, objectPool.getMaxActive());
assertEquals(12, objectPool.getMaxTotal());
assertEquals(11, objectPool.getMaxIdle());
assertEquals(13, objectPool.getMaxWait());
assertEquals(14, objectPool.getMinIdle());
assertEquals(0, objectPool.getWhenExhaustedAction());
}
@Test
public void verifyParsePoolingValidationSet() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/ldap-namespace-config-pooling-test-specified.xml");
ContextSource outerContextSource = ctx.getBean(ContextSource.class);
assertNotNull(outerContextSource);
ContextSource pooledContextSource = ((TransactionAwareContextSourceProxy) outerContextSource).getTarget();
assertNotNull(pooledContextSource);
GenericKeyedObjectPool objectPool = (GenericKeyedObjectPool) getInternalState(pooledContextSource, "keyedObjectPool");
assertEquals(123, objectPool.getMinEvictableIdleTimeMillis());
assertEquals(321, objectPool.getTimeBetweenEvictionRunsMillis());
assertEquals(22, objectPool.getNumTestsPerEvictionRun());
Object objectFactory = getInternalState(pooledContextSource, "dirContextPoolableObjectFactory");
DefaultDirContextValidator validator = (DefaultDirContextValidator) getInternalState(objectFactory, "dirContextValidator");
assertEquals("ou=test", validator.getBase());
assertEquals("objectclass=person", validator.getFilter());
SearchControls searchControls = ctx.getBean(SearchControls.class);
assertEquals("objectclass=person", validator.getFilter());
assertSame(searchControls, validator.getSearchControls());
}
}

View File

@@ -0,0 +1,10 @@
<?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 />
</beans>

View File

@@ -0,0 +1,13 @@
<?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:pooling max-active="10" max-idle="11" max-total="12" max-wait="13" min-idle="14" when-exhausted="FAIL"/>
</ldap:context-source>
<ldap:ldap-template />
</beans>

View File

@@ -0,0 +1,13 @@
<?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:pooling />
</ldap:context-source>
<ldap:ldap-template />
</beans>

View File

@@ -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.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:pooling
test-on-borrow="true"
test-on-return="true"
test-while-idle="true"
min-evictable-time-millis="123"
eviction-run-interval-millis="321"
tests-per-eviction-run="22"
validation-query-base="ou=test"
validation-query-filter="objectclass=person"
validation-query-search-controls-ref="searchControls"/>
</ldap:context-source>
<bean class="javax.naming.directory.SearchControls" id="searchControls" />
<ldap:ldap-template />
</beans>

View File

@@ -0,0 +1,14 @@
<?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:transaction-manager>
<ldap:default-renaming-strategy temp-suffix="_thisisthesuffix"/>
</ldap:transaction-manager>
</beans>

View File

@@ -0,0 +1,14 @@
<?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:transaction-manager>
<ldap:default-renaming-strategy />
</ldap:transaction-manager>
</beans>

View File

@@ -0,0 +1,14 @@
<?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:transaction-manager>
<ldap:different-subtree-renaming-strategy subtree-node="ou=temp" />
</ldap:transaction-manager>
</beans>

View File

@@ -0,0 +1,29 @@
<?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
id="myContextSource"
password="apassword"
url="ldap://localhost:389"
username="uid=admin"
base="dc=261consulting,dc=com"
anonymous-read-only="true"
authentication-strategy-ref="authenticationStrategy"
native-pooling="true"
referral="follow" />
<ldap:ldap-template context-source-ref="myContextSource"
count-limit="100"
time-limit="200"
ignore-name-not-found="true"
ignore-partial-result="true"
search-scope="OBJECT"
odm-ref="odm"/>
<bean id="authenticationStrategy" class="org.springframework.ldap.core.support.DefaultTlsDirContextAuthenticationStrategy" />
<bean id="odm" class="org.springframework.ldap.odm.core.impl.DefaultObjectDirectoryMapper" />
</beans>