Added SortControlDirContextProcessor to sandbox, because no sort support in openldap.
This commit is contained in:
@@ -1,53 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/itest-classes" path="src/itest/java"/>
|
||||
<classpathentry kind="src" output="target/itest-openldap-classes" path="src/itest-openldap/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="lib/global/commons-logging.jar" sourcepath="lib/source/commons-logging-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-beans.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-context.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-core.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-dao.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/spring-mock.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/gsbase.jar"/>
|
||||
<classpathentry kind="lib" path="lib/global/commons-lang.jar" sourcepath="lib/source/commons-lang-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/commons-collections.jar" sourcepath="lib/source/commons-collections-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/junit.jar" sourcepath="lib/source/junit-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/easymock.jar" sourcepath="lib/source/easymock-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/clover.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/ehcache.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/ehcache-constructs.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/jxl.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/cglib-nodep.jar"/>
|
||||
<classpathentry kind="lib" path="lib/buildtime/acegi-security.jar" sourcepath="lib/source/acegi-security-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/antlr.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-core.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-core-shared.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/jdbm.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/shared-asn1.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/shared-ldap.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/slf4j-log4j12.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/log4j.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-server-jndi.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-protocol-shared.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-protocol-changepw.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-protocol-kerberos.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-kerberos-shared.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/mina-core.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/mina-filter-ssl.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-server-main.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-protocol-ldap.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/junit-addons.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/DDSteps.jar"/>
|
||||
<classpathentry kind="lib" path="lib/global/ldapbp.jar"/>
|
||||
<classpathentry kind="lib" path="lib/buildtime/spring-jdbc.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/buildtime/spring-jpa.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/spring-aop.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/aopalliance.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/backport-util-concurrent.jar"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-ldap.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/shared-asn1-codec.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/itest-classes" path="src/itest/java"/>
|
||||
<classpathentry kind="src" output="target/itest-openldap-classes" path="src/itest-openldap/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="lib/global/commons-logging.jar" sourcepath="lib/source/commons-logging-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-beans.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-context.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-core.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-dao.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/spring-mock.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/gsbase.jar"/>
|
||||
<classpathentry kind="lib" path="lib/global/commons-lang.jar" sourcepath="lib/source/commons-lang-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/global/commons-collections.jar" sourcepath="lib/source/commons-collections-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/junit.jar" sourcepath="lib/source/junit-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/easymock.jar" sourcepath="lib/source/easymock-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/clover.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/ehcache.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/ehcache-constructs.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/jxl.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/cglib-nodep.jar"/>
|
||||
<classpathentry kind="lib" path="lib/buildtime/acegi-security.jar" sourcepath="lib/source/acegi-security-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/antlr.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-core.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-core-shared.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/jdbm.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/shared-asn1.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/shared-ldap.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/slf4j-log4j12.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/log4j.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-server-jndi.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-protocol-shared.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-protocol-changepw.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-protocol-kerberos.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-kerberos-shared.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/mina-core.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/mina-filter-ssl.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-server-main.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/apacheds-protocol-ldap.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/junit-addons.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/DDSteps.jar"/>
|
||||
<classpathentry kind="lib" path="lib/global/ldapbp.jar"/>
|
||||
<classpathentry kind="lib" path="lib/buildtime/spring-jdbc.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/buildtime/spring-jpa.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/spring-aop.jar" sourcepath="lib/source/spring-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/aopalliance.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/backport-util-concurrent.jar"/>
|
||||
<classpathentry kind="lib" path="lib/global/spring-ldap.jar" sourcepath="lib/source/spring-ldap-src.zip"/>
|
||||
<classpathentry kind="lib" path="lib/test/shared-asn1-codec.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
<property name="urls" value="${urls}" />
|
||||
<property name="userDn" value="${userDn}" />
|
||||
<property name="password" value="${password}" />
|
||||
<property name="dirObjectFactory" value="org.springframework.ldap.core.DefaultDirObjectFactory" />
|
||||
<property name="base" value="${base}" />
|
||||
<property name="anonymousReadOnly" value="false" />
|
||||
</bean>
|
||||
|
||||
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.control;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
|
||||
import org.springframework.ldap.Person;
|
||||
import org.springframework.ldap.core.AttributesMapper;
|
||||
import org.springframework.ldap.core.CollectingNameClassPairCallbackHandler;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.ldap.core.SearchExecutor;
|
||||
import org.springframework.ldap.support.control.SortControlDirContextProcessor;
|
||||
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
|
||||
|
||||
/**
|
||||
* Tests the still experimental sorted search result capability of LdapTemplate.
|
||||
*
|
||||
* @author Ulrik Sandberg
|
||||
*/
|
||||
public class LdapTemplateSortedSearchITest extends
|
||||
AbstractDependencyInjectionSpringContextTests {
|
||||
|
||||
private static final Name BASE = DistinguishedName.EMPTY_PATH;
|
||||
|
||||
private static final String FILTER_STRING = "(&(objectclass=ikeaperson)(cn=gor*))";
|
||||
|
||||
private LdapTemplate tested;
|
||||
|
||||
private CollectingNameClassPairCallbackHandler callbackHandler;
|
||||
|
||||
private SearchControls searchControls;
|
||||
|
||||
protected String[] getConfigLocations() {
|
||||
return new String[] { "/conf/ldapTemplateTestContext-openldap.xml" };
|
||||
}
|
||||
|
||||
protected void onSetUp() throws Exception {
|
||||
super.onSetUp();
|
||||
PersonAttributesMapper mapper = new PersonAttributesMapper();
|
||||
callbackHandler = tested.new AttributesMapperCallbackHandler(mapper);
|
||||
searchControls = new SearchControls();
|
||||
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
}
|
||||
|
||||
protected void onTearDown() throws Exception {
|
||||
super.onTearDown();
|
||||
callbackHandler = null;
|
||||
tested = null;
|
||||
searchControls = null;
|
||||
}
|
||||
|
||||
public void testSearch_SortControl() {
|
||||
SearchExecutor searchExecutor = new SearchExecutor() {
|
||||
public NamingEnumeration executeSearch(DirContext ctx)
|
||||
throws NamingException {
|
||||
return ctx.search(BASE, FILTER_STRING, searchControls);
|
||||
}
|
||||
};
|
||||
SortControlDirContextProcessor requestControl;
|
||||
|
||||
// Prepare for first search
|
||||
requestControl = new SortControlDirContextProcessor("cn");
|
||||
tested.search(searchExecutor, callbackHandler, requestControl);
|
||||
int resultCode = requestControl.getResultCode();
|
||||
boolean sorted = requestControl.isSorted();
|
||||
assertTrue("Search result should have been sorted: " + resultCode, sorted);
|
||||
List list = callbackHandler.getList();
|
||||
assertSortedList(list);
|
||||
}
|
||||
|
||||
public void testSearch_SortControl_ConvenienceMethod() {
|
||||
SortControlDirContextProcessor requestControl;
|
||||
|
||||
// Prepare for first search
|
||||
requestControl = new SortControlDirContextProcessor("cn");
|
||||
tested.search(BASE, FILTER_STRING, searchControls, callbackHandler,
|
||||
requestControl);
|
||||
int resultCode = requestControl.getResultCode();
|
||||
boolean sorted = requestControl.isSorted();
|
||||
assertTrue("Search result should have been sorted: " + resultCode, sorted);
|
||||
List list = callbackHandler.getList();
|
||||
assertSortedList(list);
|
||||
}
|
||||
|
||||
private void assertSortedList(List list) {
|
||||
Person person;
|
||||
assertEquals(6, list.size());
|
||||
person = (Person) list.get(0);
|
||||
assertEquals("Goran Milenkovic", person.getFullname());
|
||||
person = (Person) list.get(1);
|
||||
assertEquals("Goran Sundberg", person.getFullname());
|
||||
person = (Person) list.get(2);
|
||||
assertEquals("Goran Westerberg", person.getFullname());
|
||||
person = (Person) list.get(3);
|
||||
assertEquals("Gorana Milicevic", person.getFullname());
|
||||
person = (Person) list.get(4);
|
||||
assertEquals("Gordana Canic", person.getFullname());
|
||||
person = (Person) list.get(5);
|
||||
assertEquals("Gordana Russ", person.getFullname());
|
||||
}
|
||||
|
||||
public void setTested(LdapTemplate tested) {
|
||||
this.tested = tested;
|
||||
}
|
||||
|
||||
private class PersonAttributesMapper implements AttributesMapper {
|
||||
|
||||
/**
|
||||
* Maps the given attributes into a {@link Person} object.
|
||||
*
|
||||
* @see org.springframework.ldap.core.AttributesMapper#mapFromAttributes(javax.naming.directory.Attributes)
|
||||
*/
|
||||
public Object mapFromAttributes(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("givenName").get());
|
||||
return person;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ldap;
|
||||
package org.springframework.ldap.control;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -21,6 +21,7 @@ import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.SearchControls;
|
||||
|
||||
import org.springframework.ldap.Person;
|
||||
import org.springframework.ldap.core.AttributesMapper;
|
||||
import org.springframework.ldap.core.CollectingNameClassPairCallbackHandler;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
@@ -37,7 +38,7 @@ import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
|
||||
public class LdapTemplateVirtualListViewSearchITest extends
|
||||
AbstractDependencyInjectionSpringContextTests {
|
||||
|
||||
private static final String BASE_STRING = "o=ikea.com";
|
||||
private static final String BASE_STRING = "";
|
||||
|
||||
private static final String FILTER_STRING = "(&(objectclass=ikeaperson))";
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.support.control;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.ldap.Control;
|
||||
import javax.naming.ldap.LdapContext;
|
||||
|
||||
import org.springframework.ldap.control.AbstractRequestControlDirContextProcessor;
|
||||
import org.springframework.ldap.control.CreateControlFailedException;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import com.sun.jndi.ldap.ctl.SortControl;
|
||||
import com.sun.jndi.ldap.ctl.SortResponseControl;
|
||||
|
||||
/**
|
||||
* DirContextProcessor implementation for managing the {@link SortControl}.
|
||||
*
|
||||
* @author Ulrik Sandberg
|
||||
*/
|
||||
public class SortControlDirContextProcessor extends
|
||||
AbstractRequestControlDirContextProcessor {
|
||||
|
||||
private static final Class DEFAULT_RESPONSE_CONTROL = SortResponseControl.class;
|
||||
|
||||
private static final boolean CRITICAL_CONTROL = true;
|
||||
|
||||
private static final String JAVA5_RESPONSE_CONTROL = "javax.naming.ldap.SortResponseControl";
|
||||
|
||||
/**
|
||||
* What key to sort on.
|
||||
*/
|
||||
private String sortKey;
|
||||
|
||||
/**
|
||||
* Whether the search result actually was sorted.
|
||||
*/
|
||||
private boolean sorted;
|
||||
|
||||
/**
|
||||
* The result code of the supposedly sorted search.
|
||||
*/
|
||||
private int resultCode;
|
||||
|
||||
private Class responseControlClass = DEFAULT_RESPONSE_CONTROL;
|
||||
|
||||
private Class fallbackResponseControlClass;
|
||||
|
||||
private Class currentResponseControlClass;
|
||||
|
||||
public SortControlDirContextProcessor(String sortKey) {
|
||||
this.sortKey = sortKey;
|
||||
fallbackResponseControlClass = loadFallbackResponseControlClass();
|
||||
setSorted(false);
|
||||
setResultCode(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the class of the expected ResponseControl for the sorted result
|
||||
* response. The default is {@link SortResponseControl}.
|
||||
*
|
||||
* @param responseControlClass
|
||||
* Class of the expected response control.
|
||||
*/
|
||||
public void setResponseControlClass(Class responseControlClass) {
|
||||
this.responseControlClass = responseControlClass;
|
||||
}
|
||||
|
||||
public boolean isSorted() {
|
||||
return sorted;
|
||||
}
|
||||
|
||||
private void setSorted(boolean sorted) {
|
||||
this.sorted = sorted;
|
||||
}
|
||||
|
||||
public int getResultCode() {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
private void setResultCode(int sortResult) {
|
||||
this.resultCode = sortResult;
|
||||
}
|
||||
|
||||
public String getSortKey() {
|
||||
return sortKey;
|
||||
}
|
||||
|
||||
public void setSortKey(String sortKey) {
|
||||
this.sortKey = sortKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see org.springframework.ldap.control.AbstractRequestControlDirContextProcessor#createRequestControl()
|
||||
*/
|
||||
public Control createRequestControl() {
|
||||
try {
|
||||
return new SortControl(new String[] { sortKey }, CRITICAL_CONTROL);
|
||||
} catch (IOException e) {
|
||||
throw new CreateControlFailedException(
|
||||
"Error creating SortControl", e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @see org.springframework.ldap.core.DirContextProcessor#postProcess(javax.naming.directory.DirContext)
|
||||
*/
|
||||
public void postProcess(DirContext ctx) throws NamingException {
|
||||
// initialize from property
|
||||
currentResponseControlClass = responseControlClass;
|
||||
|
||||
LdapContext ldapContext = (LdapContext) ctx;
|
||||
Control[] responseControls = ldapContext.getResponseControls();
|
||||
|
||||
if (responseControls == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Go through response controls and get info, regardless of class
|
||||
for (int i = 0; i < responseControls.length; i++) {
|
||||
Control responseControl = responseControls[i];
|
||||
|
||||
// check for match, try fallback otherwise
|
||||
if (isSortResponseControl(responseControl)) {
|
||||
Object control = responseControl;
|
||||
Boolean result = (Boolean) invokeMethod("isSorted",
|
||||
currentResponseControlClass, control);
|
||||
setSorted(result.booleanValue());
|
||||
Integer code = (Integer) invokeMethod("getResultCode",
|
||||
currentResponseControlClass, control);
|
||||
setResultCode(code.intValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given control matches a sort response control. Try the
|
||||
* fallback class from Java5 if there is no match. Set the
|
||||
* {@link #currentResponseControlClass} to the fallback if it matches.
|
||||
*
|
||||
* @param responseControl
|
||||
* the control to check for a match
|
||||
* @return whether the control is a paged results response control
|
||||
*/
|
||||
private boolean isSortResponseControl(Control responseControl) {
|
||||
if (responseControl.getClass().isAssignableFrom(
|
||||
currentResponseControlClass)) {
|
||||
return true;
|
||||
}
|
||||
if (fallbackResponseControlClass != null
|
||||
&& responseControl.getClass().isAssignableFrom(
|
||||
fallbackResponseControlClass)) {
|
||||
currentResponseControlClass = fallbackResponseControlClass;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Class loadFallbackResponseControlClass() {
|
||||
Class fallbackResponseControlClass = null;
|
||||
try {
|
||||
fallbackResponseControlClass = Class
|
||||
.forName(JAVA5_RESPONSE_CONTROL);
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.debug("Could not load Java5 response control class "
|
||||
+ JAVA5_RESPONSE_CONTROL);
|
||||
}
|
||||
return fallbackResponseControlClass;
|
||||
}
|
||||
|
||||
private Object invokeMethod(String method, Class clazz, Object control) {
|
||||
// For Spring 2.0 ReflectionUtils could be used for all of this, but
|
||||
// since we still want to support the 1.2 branch we do it manually and
|
||||
// only use the stuff present in 1.2.8.
|
||||
Method actualMethod = null;
|
||||
Object retval = null;
|
||||
try {
|
||||
actualMethod = clazz.getMethod(method, new Class[0]);
|
||||
} catch (SecurityException e) {
|
||||
ReflectionUtils.handleReflectionException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
ReflectionUtils.handleReflectionException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
retval = actualMethod.invoke(control, new Object[0]);
|
||||
} catch (IllegalArgumentException e) {
|
||||
ReflectionUtils.handleReflectionException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
ReflectionUtils.handleReflectionException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
ReflectionUtils.handleReflectionException(e);
|
||||
}
|
||||
|
||||
// Retval will be set unless an exception has been thrown.
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
@@ -173,6 +173,10 @@ public class VirtualListViewRequestControl implements DirContextProcessor {
|
||||
LdapContext ldapContext = (LdapContext) ctx;
|
||||
Control[] responseControls = ldapContext.getResponseControls();
|
||||
|
||||
if (responseControls == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Go through response controls and get info, regardless of class
|
||||
for (int i = 0; i < responseControls.length; i++) {
|
||||
Control responseControl = responseControls[i];
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.control;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.naming.ldap.Control;
|
||||
import javax.naming.ldap.LdapContext;
|
||||
import javax.naming.ldap.PagedResultsControl;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.MockControl;
|
||||
import org.springframework.ldap.support.control.SortControlDirContextProcessor;
|
||||
|
||||
import com.sun.jndi.ldap.Ber;
|
||||
import com.sun.jndi.ldap.BerDecoder;
|
||||
import com.sun.jndi.ldap.BerEncoder;
|
||||
import com.sun.jndi.ldap.ctl.DirSyncResponseControl;
|
||||
import com.sun.jndi.ldap.ctl.SortControl;
|
||||
import com.sun.jndi.ldap.ctl.SortResponseControl;
|
||||
|
||||
/**
|
||||
* Unit tests for the SortControlDirContextProcessor class.
|
||||
* {@link javax.naming.ldap.SortControl}
|
||||
* {@link javax.naming.ldap.SortResponseControl}
|
||||
* {@link PagedResultsControl}
|
||||
*
|
||||
* @author Ulrik Sandberg
|
||||
*/
|
||||
public class SortControlDirContextProcessorTest extends TestCase {
|
||||
|
||||
private MockControl ldapContextControl;
|
||||
|
||||
private LdapContext ldapContextMock;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
// Create ldapContext mock
|
||||
ldapContextControl = MockControl.createControl(LdapContext.class);
|
||||
ldapContextMock = (LdapContext) ldapContextControl.getMock();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
ldapContextControl = null;
|
||||
ldapContextMock = null;
|
||||
}
|
||||
|
||||
protected void replay() {
|
||||
ldapContextControl.replay();
|
||||
}
|
||||
|
||||
protected void verify() {
|
||||
ldapContextControl.verify();
|
||||
}
|
||||
|
||||
public void testCreateRequestControl() throws Exception {
|
||||
SortControlDirContextProcessor tested = new SortControlDirContextProcessor(
|
||||
"key");
|
||||
|
||||
SortControl control = (SortControl) tested.createRequestControl();
|
||||
assertNotNull(control);
|
||||
}
|
||||
|
||||
public void testPostProcess() throws Exception {
|
||||
byte sortResult = 0; // success
|
||||
|
||||
byte[] value = encodeValue(sortResult);
|
||||
SortResponseControl control = new SortResponseControl(
|
||||
"dummy", true, value);
|
||||
|
||||
ldapContextControl.expectAndDefaultReturn(ldapContextMock
|
||||
.getResponseControls(), new Control[] { control });
|
||||
|
||||
SortControlDirContextProcessor tested = new SortControlDirContextProcessor("key");
|
||||
|
||||
replay();
|
||||
|
||||
tested.postProcess(ldapContextMock);
|
||||
|
||||
verify();
|
||||
|
||||
assertEquals(true, tested.isSorted());
|
||||
assertEquals(0, tested.getResultCode());
|
||||
}
|
||||
|
||||
public void testPostProcess_NonSuccess() throws Exception {
|
||||
byte sortResult = 1;
|
||||
|
||||
byte[] value = encodeValue(sortResult);
|
||||
SortResponseControl control = new SortResponseControl(
|
||||
"dummy", true, value);
|
||||
|
||||
ldapContextControl.expectAndDefaultReturn(ldapContextMock
|
||||
.getResponseControls(), new Control[] { control });
|
||||
|
||||
SortControlDirContextProcessor tested = new SortControlDirContextProcessor("key");
|
||||
|
||||
replay();
|
||||
|
||||
tested.postProcess(ldapContextMock);
|
||||
|
||||
verify();
|
||||
|
||||
assertEquals(false, tested.isSorted());
|
||||
assertEquals(1, tested.getResultCode());
|
||||
}
|
||||
|
||||
public void testPostProcess_InvalidResponseControl() throws Exception {
|
||||
int resultSize = 50;
|
||||
byte pageSize = 8;
|
||||
|
||||
byte[] value = new byte[1];
|
||||
value[0] = pageSize;
|
||||
byte[] cookie = encodeDirSyncValue(resultSize, value);
|
||||
|
||||
// Using another response control to verify that it is ignored
|
||||
DirSyncResponseControl control = new DirSyncResponseControl("dummy",
|
||||
true, cookie);
|
||||
|
||||
ldapContextControl.expectAndDefaultReturn(ldapContextMock
|
||||
.getResponseControls(), new Control[] { control });
|
||||
|
||||
SortControlDirContextProcessor tested = new SortControlDirContextProcessor("key");
|
||||
|
||||
replay();
|
||||
|
||||
tested.postProcess(ldapContextMock);
|
||||
|
||||
verify();
|
||||
|
||||
assertEquals(false, tested.isSorted());
|
||||
}
|
||||
|
||||
public void testBerDecoding() throws Exception {
|
||||
int sortResult = 53; // unwilling to perform
|
||||
byte[] encoded = encodeValue(sortResult);
|
||||
|
||||
BerDecoder ber = new BerDecoder(encoded, 0, encoded.length);
|
||||
|
||||
ber.parseSeq(null);
|
||||
int actualSortResult = ber.parseEnumeration();
|
||||
|
||||
assertEquals("sortResult,", 53, actualSortResult);
|
||||
}
|
||||
|
||||
private byte[] encodeValue(int sortResult) throws IOException {
|
||||
|
||||
// build the ASN.1 encoding
|
||||
BerEncoder ber = new BerEncoder(10);
|
||||
|
||||
ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
|
||||
ber.encodeInt(sortResult, Ber.ASN_ENUMERATED);
|
||||
ber.endSeq();
|
||||
|
||||
return ber.getTrimmedBuf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a value suitable for the DirSyncResponseControl used in a test.
|
||||
*/
|
||||
private byte[] encodeDirSyncValue(int pageSize, byte[] cookie)
|
||||
throws IOException {
|
||||
|
||||
// build the ASN.1 encoding
|
||||
BerEncoder ber = new BerEncoder(10 + cookie.length);
|
||||
|
||||
ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
|
||||
ber.encodeInt(1); // flag
|
||||
ber.encodeInt(pageSize); // maxReturnLength
|
||||
ber.encodeOctetString(cookie, Ber.ASN_OCTET_STR);
|
||||
ber.endSeq();
|
||||
|
||||
return ber.getTrimmedBuf();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user