diff --git a/sandbox/src/main/java/org/springframework/ldap/control/VirtualListViewControlAggregateDirContextProcessor.java b/sandbox/src/main/java/org/springframework/ldap/control/VirtualListViewControlAggregateDirContextProcessor.java index d1675cd7..3855edbe 100644 --- a/sandbox/src/main/java/org/springframework/ldap/control/VirtualListViewControlAggregateDirContextProcessor.java +++ b/sandbox/src/main/java/org/springframework/ldap/control/VirtualListViewControlAggregateDirContextProcessor.java @@ -21,16 +21,42 @@ import org.springframework.ldap.core.support.AggregateDirContextProcessor; * AggregateDirContextProcessor implementation for managing a virtual list view * by aggregating DirContextProcessor implementations for a VirtualListViewControl * and its required companion SortControl. - * + * * @author Mattias Hellborg Arthursson * @author Ulrik Sandberg + * @author Marius Scurtescu */ -public class VirtualListViewControlAggregateDirContextProcessor extends AggregateDirContextProcessor { +public class VirtualListViewControlAggregateDirContextProcessor extends AggregateDirContextProcessor +{ + private SortControlDirContextProcessor _sortControlDirContextProcessor; + private VirtualListViewControlDirContextProcessor _virtualListViewControlDirContextProcessor; - private VirtualListViewControlDirContextProcessor vlvProcessor; + public VirtualListViewControlAggregateDirContextProcessor(String sortKey, int pageSize) + { + this( + new SortControlDirContextProcessor(sortKey), + new VirtualListViewControlDirContextProcessor(pageSize) + ); + } - private SortControlDirContextProcessor sortControlProcessor; + public VirtualListViewControlAggregateDirContextProcessor(String sortKey, int pageSize, int targetOffset, int listSize, VirtualListViewResultsCookie cookie) + { + this( + new SortControlDirContextProcessor(sortKey), + new VirtualListViewControlDirContextProcessor(pageSize, targetOffset, listSize, cookie) + ); + } - public VirtualListViewControlAggregateDirContextProcessor(String sortKey, int pageSize) { + public VirtualListViewControlAggregateDirContextProcessor(SortControlDirContextProcessor sortControlDirContextProcessor, VirtualListViewControlDirContextProcessor virtualListViewControlDirContextProcessor) + { + _sortControlDirContextProcessor = sortControlDirContextProcessor; + _virtualListViewControlDirContextProcessor = virtualListViewControlDirContextProcessor; + + addDirContextProcessor(sortControlDirContextProcessor); + addDirContextProcessor(virtualListViewControlDirContextProcessor); + } + + public VirtualListViewResultsCookie getCookie() { + return _virtualListViewControlDirContextProcessor.getCookie(); } } diff --git a/sandbox/src/main/java/org/springframework/ldap/control/VirtualListViewControlDirContextProcessor.java b/sandbox/src/main/java/org/springframework/ldap/control/VirtualListViewControlDirContextProcessor.java index 8e2c646c..df36688b 100644 --- a/sandbox/src/main/java/org/springframework/ldap/control/VirtualListViewControlDirContextProcessor.java +++ b/sandbox/src/main/java/org/springframework/ldap/control/VirtualListViewControlDirContextProcessor.java @@ -16,70 +16,62 @@ package org.springframework.ldap.control; -import java.io.IOException; 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.CreateControlFailedException; -import org.springframework.ldap.core.DirContextProcessor; import org.springframework.ldap.support.LdapUtils; import org.springframework.util.ReflectionUtils; -import com.sun.jndi.ldap.ctl.SortControl; -import com.sun.jndi.ldap.ctl.VirtualListViewControl; -import com.sun.jndi.ldap.ctl.VirtualListViewResponseControl; - /** * DirContextProcessor implementation for managing a virtual list view. *

* This is the request control syntax: - * + * *

- * VirtualListViewRequest ::= SEQUENCE { 
- *        beforeCount    INTEGER (0..maxInt), 
- *        afterCount     INTEGER (0..maxInt), 
- *        target       CHOICE { 
- *                       byOffset        [0] SEQUENCE {                           
- *                            offset          INTEGER (1 .. maxInt), 
- *                            contentCount    INTEGER (0 .. maxInt) }, 
- *                       greaterThanOrEqual [1] AssertionValue }, 
+ * VirtualListViewRequest ::= SEQUENCE {
+ *        beforeCount    INTEGER (0..maxInt),
+ *        afterCount     INTEGER (0..maxInt),
+ *        target       CHOICE {
+ *                       byOffset        [0] SEQUENCE {
+ *                            offset          INTEGER (1 .. maxInt),
+ *                            contentCount    INTEGER (0 .. maxInt) },
+ *                       greaterThanOrEqual [1] AssertionValue },
  *        contextID     OCTET STRING OPTIONAL }
  * 
- * + * *

* This is the response control syntax: - * + * *

- * VirtualListViewResponse ::= SEQUENCE { 
- *        targetPosition    INTEGER (0 .. maxInt), 
- *        contentCount     INTEGER (0 .. maxInt), 
- *        virtualListViewResult ENUMERATED { 
- *             success (0), 
- *             operationsError (1), 
- *             protocolError (3), 
- *             unwillingToPerform (53), 
- *             insufficientAccessRights (50), 
- *             timeLimitExceeded (3), 
- *             adminLimitExceeded (11), 
- *             innapropriateMatching (18), 
- *             sortControlMissing (60), 
- *             offsetRangeError (61), 
- *             other(80), 
- *             ... }, 
+ * VirtualListViewResponse ::= SEQUENCE {
+ *        targetPosition    INTEGER (0 .. maxInt),
+ *        contentCount     INTEGER (0 .. maxInt),
+ *        virtualListViewResult ENUMERATED {
+ *             success (0),
+ *             operationsError (1),
+ *             protocolError (3),
+ *             unwillingToPerform (53),
+ *             insufficientAccessRights (50),
+ *             timeLimitExceeded (3),
+ *             adminLimitExceeded (11),
+ *             innapropriateMatching (18),
+ *             sortControlMissing (60),
+ *             offsetRangeError (61),
+ *             other(80),
+ *             ... },
  *        contextID     OCTET STRING OPTIONAL }
  * 
- * + * * @author Ulrik Sandberg + * @author Marius Scurtescu * @see LDAP Extensions for Scrolling View Browsing of Search Results */ -public class VirtualListViewControlDirContextProcessor implements - DirContextProcessor { - - private static final Class DEFAULT_RESPONSE_CONTROL = VirtualListViewResponseControl.class; +class VirtualListViewControlDirContextProcessor extends AbstractFallbackRequestAndResponseControlDirContextProcessor +{ + private static final String DEFAULT_REQUEST_CONTROL = "com.sun.jndi.ldap.ctl.VirtualListViewControl"; + private static final String DEFAULT_RESPONSE_CONTROL = "com.sun.jndi.ldap.ctl.VirtualListViewResponseControl"; private static final boolean CRITICAL_CONTROL = true; @@ -93,14 +85,10 @@ public class VirtualListViewControlDirContextProcessor implements private NamingException exception; - private int resultCode; - - private Class responseControlClass = DEFAULT_RESPONSE_CONTROL; - private boolean offsetPercentage; public VirtualListViewControlDirContextProcessor(int pageSize) { - this(pageSize, 0, 0, null); + this(pageSize, 1, 0, null); } public VirtualListViewControlDirContextProcessor(int pageSize, @@ -109,6 +97,13 @@ public class VirtualListViewControlDirContextProcessor implements this.targetOffset = targetOffset; this.listSize = listSize; this.cookie = cookie; + + defaultRequestControl = DEFAULT_REQUEST_CONTROL; + defaultResponseControl = DEFAULT_RESPONSE_CONTROL; + fallbackRequestControl = DEFAULT_REQUEST_CONTROL; + fallbackResponseControl = DEFAULT_RESPONSE_CONTROL; + + loadControlClasses(); } public VirtualListViewResultsCookie getCookie() { @@ -127,25 +122,10 @@ public class VirtualListViewControlDirContextProcessor implements return exception; } - public int getResultCode() { - return resultCode; - } - public int getTargetOffset() { return targetOffset; } - /** - * Set the class of the expected ResponseControl for the paged results - * response. The default is {@link VirtualListViewResponseControl}. - * - * @param responseControlClass - * Class of the expected response control. - */ - public void setResponseControlClass(Class responseControlClass) { - this.responseControlClass = responseControlClass; - } - /** * Set whether the targetOffset should be interpreted as * percentage of the list or an offset into the list. @@ -155,122 +135,90 @@ public class VirtualListViewControlDirContextProcessor implements this.offsetPercentage = isPercentage; } - public void preProcess(DirContext ctx) throws NamingException { - LdapContext ldapContext; - if (ctx instanceof LdapContext) { - ldapContext = (LdapContext) ctx; - } else { - throw new IllegalArgumentException( - "Request Control operations require LDAPv3 - " - + "Context must be of type LdapContext"); - } - - Control[] requestControls = ldapContext.getRequestControls(); - Control newControl = createRequestControl(); - - Control[] newControls = new Control[requestControls.length + 2]; - for (int i = 0; i < requestControls.length; i++) { - newControls[i] = requestControls[i]; - } - - SortControl sortControl; - try { - sortControl = new SortControl(new String[] { "cn" }, true); - } catch (IOException e) { - throw new CreateControlFailedException( - "Couldn't create SortControl", e); - } - // Add the new Controls at the end of the array. - newControls[newControls.length - 2] = sortControl; - newControls[newControls.length - 1] = newControl; - - ldapContext.setRequestControls(newControls); + public boolean isOffsetPercentage() + { + return offsetPercentage; } /* * @see org.springframework.ldap.control.AbstractRequestControlDirContextProcessor#createRequestControl() */ - public Control createRequestControl() { - try { - VirtualListViewControl virtualListViewControl; - if (offsetPercentage) { - // Request a view of a portion of the list centered around a - // given target entry. The position of the target entry is - // estimated as a percentage of the list. - virtualListViewControl = new VirtualListViewControl( - targetOffset, pageSize, CRITICAL_CONTROL); - } else { - // Request a view of a portion of the list with the specified - // number of entries before and after a given target entry. The - // target entry is identified by means of an offset into the - // list. - virtualListViewControl = new VirtualListViewControl( - targetOffset, listSize, 0, pageSize - 1, - CRITICAL_CONTROL); - } - if (cookie != null) { - virtualListViewControl.setContextID(cookie.getCookie()); - } - return virtualListViewControl; - } catch (IOException e) { - throw new CreateControlFailedException( - "Error creating VirtualListViewControl", e); + public Control createRequestControl() + { + Control control; + + if (offsetPercentage) + { + control = super.createRequestControl( + new Class[] { + int.class, + int.class, + boolean.class + }, + new Object[] { + Integer.valueOf(targetOffset), + Integer.valueOf(pageSize), + Boolean.valueOf(CRITICAL_CONTROL) + } + ); + } + else + { + control = super.createRequestControl( + new Class[] { + int.class, + int.class, + int.class, + int.class, + boolean.class + }, + new Object[] { + Integer.valueOf(targetOffset), + Integer.valueOf(listSize), + Integer.valueOf(0), + Integer.valueOf(pageSize - 1), + Boolean.valueOf(CRITICAL_CONTROL) + } + ); + } + + if (cookie != null) + { + invokeMethod( + "setContextID", + requestControlClass, + control, + new Class[] {byte[].class}, + new Object[] {cookie.getCookie()} + ); + } + + return control; + } + + protected void handleResponse(Object control) + { + byte[] result = (byte[]) invokeMethod("getContextID", + responseControlClass, control); + Integer listSize = (Integer) invokeMethod("getListSize", + responseControlClass, control); + Integer targetOffset = (Integer) invokeMethod( + "getTargetOffset", responseControlClass, control); + this.exception = (NamingException) invokeMethod("getException", + responseControlClass, control); + + this.cookie = new VirtualListViewResultsCookie(result, + targetOffset.intValue(), listSize.intValue()); + + if (exception != null) { + throw LdapUtils.convertLdapException(exception); } } - /* - * @see org.springframework.ldap.core.DirContextProcessor#postProcess(javax.naming.directory.DirContext) - */ - public void postProcess(DirContext ctx) throws NamingException { - LdapContext ldapContext = (LdapContext) ctx; - Control[] responseControls = ldapContext.getResponseControls(); + protected static Object invokeMethod(String methodName, Class clazz, Object control, Class[] paramTypes, Object[] paramValues) + { + Method method = ReflectionUtils.findMethod(clazz, methodName, paramTypes); - 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 - if (isVirtualListViewResponseControl(responseControl)) { - Object control = responseControl; - byte[] result = (byte[]) invokeMethod("getContextID", - responseControlClass, control); - Integer listSize = (Integer) invokeMethod("getListSize", - responseControlClass, control); - Integer targetOffset = (Integer) invokeMethod( - "getTargetOffset", responseControlClass, control); - this.exception = (NamingException) invokeMethod("getException", - responseControlClass, control); - - this.cookie = new VirtualListViewResultsCookie(result, - targetOffset.intValue(), listSize.intValue()); - - if (exception != null) { - throw LdapUtils.convertLdapException(exception); - } - } - } - } - - /** - * Check if the given control matches a virtual list view response control. - * - * @param responseControl - * the control to check for a match - * @return whether the control is a virtual list view response control - */ - private boolean isVirtualListViewResponseControl(Control responseControl) { - if (responseControl.getClass().isAssignableFrom(responseControlClass)) { - return true; - } - return false; - } - - private Object invokeMethod(String method, Class clazz, Object control) { - Method m = ReflectionUtils.findMethod(clazz, method, new Class[0]); - return ReflectionUtils.invokeMethod(m, control); + return ReflectionUtils.invokeMethod(method, control, paramValues); } } diff --git a/sandbox/src/test/java/org/springframework/ldap/control/VirtualListViewControlDirContextProcessorTest.java b/sandbox/src/test/java/org/springframework/ldap/control/VirtualListViewControlDirContextProcessorTest.java index ea4bd072..da981ec3 100644 --- a/sandbox/src/test/java/org/springframework/ldap/control/VirtualListViewControlDirContextProcessorTest.java +++ b/sandbox/src/test/java/org/springframework/ldap/control/VirtualListViewControlDirContextProcessorTest.java @@ -35,7 +35,7 @@ import com.sun.jndi.ldap.ctl.VirtualListViewResponseControl; /** * Unit tests for the VirtualListViewControlDirContextProcessor class. - * + * * @author Ulrik Sandberg */ public class VirtualListViewControlDirContextProcessorTest extends TestCase { @@ -71,16 +71,11 @@ public class VirtualListViewControlDirContextProcessorTest extends TestCase { ldapContextControl.verify(); } - public void testPreProcess() throws Exception { - final VirtualListViewControl control = new VirtualListViewControl(0, 3, - true); +/* public void testPreProcess() throws Exception { int pageSize = 5; - VirtualListViewControlDirContextProcessor tested = new VirtualListViewControlDirContextProcessor( - pageSize) { - public Control createRequestControl() { - return control; - } - }; + VirtualListViewControlAggregateDirContextProcessor tested = new VirtualListViewControlAggregateDirContextProcessor( + "cn", + pageSize); ldapContextControl.expectAndReturn( ldapContextMock.getRequestControls(), new Control[0]); @@ -100,7 +95,7 @@ public class VirtualListViewControlDirContextProcessorTest extends TestCase { verify(); } - +*/ public void testCreateRequestControlWithTargetAsOffset() throws Exception { int pageSize = 5; int targetOffset = 25; diff --git a/test/integration-tests-sunone/pom.xml b/test/integration-tests-sunone/pom.xml index 74323240..cf47a383 100644 --- a/test/integration-tests-sunone/pom.xml +++ b/test/integration-tests-sunone/pom.xml @@ -35,6 +35,11 @@ spring-ldap-integration-tests ${project.version} + + org.springframework.ldap + spring-ldap-sandbox + ${project.version} + org.springframework.ldap spring-ldap-core-tiger @@ -50,12 +55,18 @@ spring-aop test + com.sun ldapbp 1.0 provided + + commons-pool + commons-pool + 1.4 + gsbase gsbase diff --git a/test/integration-tests-sunone/src/test/java/org/springframework/ldap/core/LdapTemplateVirtualListViewSearchITest.java b/test/integration-tests-sunone/src/test/java/org/springframework/ldap/core/LdapTemplateVirtualListViewSearchITest.java index 38da9eab..8736f4b2 100644 --- a/test/integration-tests-sunone/src/test/java/org/springframework/ldap/core/LdapTemplateVirtualListViewSearchITest.java +++ b/test/integration-tests-sunone/src/test/java/org/springframework/ldap/core/LdapTemplateVirtualListViewSearchITest.java @@ -25,8 +25,8 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.ldap.Person; -import org.springframework.ldap.PersonContextMapper; +import org.springframework.ldap.itest.Person; +import org.springframework.ldap.itest.PersonContextMapper; import org.springframework.ldap.control.VirtualListViewControlDirContextProcessor; import org.springframework.ldap.control.VirtualListViewResultsCookie; import org.springframework.test.context.ContextConfiguration; @@ -38,7 +38,7 @@ import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; * href= * "http://www3.tools.ietf.org/html/draft-ietf-ldapext-ldapv3-vlv-09">Virtual * List View RFC draft. - * + * *
Here we walk through the client-server interaction for a * specific virtual list view example: The task is to display a list of all * 78564 persons in the US company "Ace Industry". This will be done by creating @@ -86,7 +86,7 @@ import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; * preceding entries, the target entry, and the proceeding 10 entries. The * server returns a content count of 78564 and a targetPosition of 5234 and so * the client updates its scroll bar slider to 6.7% of full scale.
- * + * * @author Ulrik Sandberg */ @ContextConfiguration(locations = { "/conf/ldapTemplateTestContext.xml" }) @@ -98,7 +98,7 @@ public class LdapTemplateVirtualListViewSearchITest extends private static final String BASE_STRING = ""; - private static final String FILTER_STRING = "(objectclass=person)"; + private static final String FILTER_STRING = "(objectClass=person)"; private SearchControls searchControls; @@ -137,11 +137,11 @@ public class LdapTemplateVirtualListViewSearchITest extends cookie = requestControl.getCookie(); // assert that total count is still 78564 - listSize = requestControl.getListSize(); + listSize = cookie.getContentCount(); assertEquals(78564, listSize); // assert that we are now at 1 - targetOffset = requestControl.getTargetOffset(); + targetOffset = cookie.getTargetPosition(); assertEquals(1, targetOffset); // assert that we got the right 20 @@ -245,7 +245,7 @@ public class LdapTemplateVirtualListViewSearchITest extends // also beforeCount and afterCount requestControl = new VirtualListViewControlDirContextProcessor(20, 5234, listSize, cookie); - + requestControl.setOffsetPercentage(true); tested.search(BASE_STRING, FILTER_STRING, searchControls, callbackHandler, requestControl); diff --git a/test/integration-tests-sunone/src/test/resources/conf/ldapTemplateTestContext.xml b/test/integration-tests-sunone/src/test/resources/conf/ldapTemplateTestContext.xml index ef677a1a..dba4710d 100644 --- a/test/integration-tests-sunone/src/test/resources/conf/ldapTemplateTestContext.xml +++ b/test/integration-tests-sunone/src/test/resources/conf/ldapTemplateTestContext.xml @@ -15,13 +15,25 @@ - + - + + + + + + + + + + + +