Moved everything from mvn-build to trunk root.

This commit is contained in:
Ulrik Sandberg
2008-10-12 21:34:09 +00:00
parent 22122636b1
commit a74ed8dafd
513 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2005-2007 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 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 Arthursson
* @author Ulrik Sandberg
*/
public class VirtualListViewControlAggregateDirContextProcessor extends AggregateDirContextProcessor {
private VirtualListViewControlDirContextProcessor vlvProcessor;
private SortControlDirContextProcessor sortControlProcessor;
public VirtualListViewControlAggregateDirContextProcessor(String sortKey, int pageSize) {
}
}

View File

@@ -0,0 +1,276 @@
/*
* Copyright 2005-2007 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 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.
* <p>
* This is the request control syntax:
*
* <pre>
* 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 }
* </pre>
*
* <p>
* This is the response control syntax:
*
* <pre>
* 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 }
* </pre>
*
* @author Ulrik Sandberg
* @see <a href="http://www3.ietf.org/proceedings/02nov/I-D/draft-ietf-ldapext-ldapv3-vlv-09.txt">LDAP Extensions for Scrolling View Browsing of Search Results</a>
*/
public class VirtualListViewControlDirContextProcessor implements
DirContextProcessor {
private static final Class DEFAULT_RESPONSE_CONTROL = VirtualListViewResponseControl.class;
private static final boolean CRITICAL_CONTROL = true;
private int pageSize;
private VirtualListViewResultsCookie cookie;
private int listSize;
private int targetOffset;
private NamingException exception;
private int resultCode;
private Class responseControlClass = DEFAULT_RESPONSE_CONTROL;
private boolean offsetPercentage;
public VirtualListViewControlDirContextProcessor(int pageSize) {
this(pageSize, 0, 0, null);
}
public VirtualListViewControlDirContextProcessor(int pageSize,
int targetOffset, int listSize, VirtualListViewResultsCookie cookie) {
this.pageSize = pageSize;
this.targetOffset = targetOffset;
this.listSize = listSize;
this.cookie = cookie;
}
public VirtualListViewResultsCookie getCookie() {
return cookie;
}
public int getPageSize() {
return pageSize;
}
public int getListSize() {
return listSize;
}
public NamingException getException() {
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 <code>targetOffset</code> should be interpreted as
* percentage of the list or an offset into the list.
* @param isPercentage <code>true</code> if targetOffset is a percentage
*/
public void setOffsetPercentage(boolean isPercentage) {
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);
}
/*
* @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);
}
}
/*
* @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();
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);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2005-2007 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 com.sun.jndi.ldap.ctl.VirtualListViewControl;
/**
* Wrapper class for the cookie returned when using the
* {@link VirtualListViewControl}.
*
* @author Ulrik Sandberg
*/
public class VirtualListViewResultsCookie {
private byte[] cookie;
private int contentCount;
private int targetPosition;
/**
* Constructor.
*
* @param cookie
* the cookie returned by a VirtualListViewResponseControl.
* @param targetPosition TODO
* @param contentCount TODO
*/
public VirtualListViewResultsCookie(byte[] cookie, int targetPosition, int contentCount) {
this.cookie = cookie;
this.targetPosition = targetPosition;
this.contentCount = contentCount;
}
/**
* Get the cookie.
*
* @return the cookie.
*/
public byte[] getCookie() {
return cookie;
}
public int getContentCount() {
return contentCount;
}
public int getTargetPosition() {
return targetPosition;
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2005-2007 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.Arrays;
import javax.naming.ldap.Control;
import org.easymock.AbstractMatcher;
public class ControlArrayMatcher extends AbstractMatcher {
protected boolean argumentMatches(Object expected, Object actual) {
Control[] expectedControls = (Control[]) expected;
Control[] actualControls = (Control[]) actual;
if (expectedControls.length != actualControls.length) {
return false;
}
for (int i = 0; i < actualControls.length; i++) {
Control actualControl = actualControls[i];
Control expectedControl = expectedControls[i];
if (actualControl == null && expectedControl != null) {
return false;
}
if (actualControl != null && expectedControl == null) {
return false;
}
if (actualControl == null && expectedControl == null) {
continue;
}
if (!actualControl.getClass().equals(expectedControl.getClass())) {
return false;
}
}
return true;
}
protected String argumentToString(Object argument) {
if (argument instanceof Control[]) {
Control[] control = (Control[]) argument;
return Arrays.toString(control);
}
return super.argumentToString(argument);
}
}

View File

@@ -0,0 +1,286 @@
/*
* Copyright 2005-2007 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 junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.OperationNotSupportedException;
import com.sun.jndi.ldap.Ber;
import com.sun.jndi.ldap.BerDecoder;
import com.sun.jndi.ldap.BerEncoder;
import com.sun.jndi.ldap.ctl.SortControl;
import com.sun.jndi.ldap.ctl.VirtualListViewControl;
import com.sun.jndi.ldap.ctl.VirtualListViewResponseControl;
/**
* Unit tests for the VirtualListViewControlDirContextProcessor class.
*
* @author Ulrik Sandberg
*/
public class VirtualListViewControlDirContextProcessorTest extends TestCase {
private static final String OID_REQUEST = "2.16.840.1.113730.3.4.9";
private static final String OID_RESPONSE = "2.16.840.1.113730.3.4.10";
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 testPreProcess() throws Exception {
final VirtualListViewControl control = new VirtualListViewControl(0, 3,
true);
int pageSize = 5;
VirtualListViewControlDirContextProcessor tested = new VirtualListViewControlDirContextProcessor(
pageSize) {
public Control createRequestControl() {
return control;
}
};
ldapContextControl.expectAndReturn(
ldapContextMock.getRequestControls(), new Control[0]);
SortControl sortControl = new SortControl(new String[] { "cn" }, true);
VirtualListViewControl vlvControl = new VirtualListViewControl(0, 0, 0,
0, true);
Control[] controls = new Control[] { sortControl, vlvControl };
ldapContextMock.setRequestControls(controls);
// just check that class names match
ldapContextControl.setMatcher(new ControlArrayMatcher());
replay();
tested.preProcess(ldapContextMock);
verify();
}
public void testCreateRequestControlWithTargetAsOffset() throws Exception {
int pageSize = 5;
int targetOffset = 25;
int listSize = 1000;
VirtualListViewControlDirContextProcessor tested = new VirtualListViewControlDirContextProcessor(
pageSize, targetOffset, listSize,
new VirtualListViewResultsCookie(new byte[0], 0, 0));
VirtualListViewControl result = (VirtualListViewControl) tested
.createRequestControl();
assertNotNull(result);
assertEquals(OID_REQUEST, result.getID());
// verify that the values have been encoded as we expect
int expectedBeforeCount = 0;
int expectedAfterCount = 4;
int expectedOffset = 25;
int expectedContentCount = listSize;
assertEncodedRequest(result.getEncodedValue(), expectedBeforeCount,
expectedAfterCount, expectedOffset, expectedContentCount,
new byte[0]);
}
public void testCreateRequestControlWithTargetAsPercentage()
throws Exception {
int pageSize = 5;
int targetPercentage = 25;
int listSize = 1000;
VirtualListViewControlDirContextProcessor tested = new VirtualListViewControlDirContextProcessor(
pageSize, targetPercentage, listSize,
new VirtualListViewResultsCookie(new byte[0], 0, 0));
tested.setOffsetPercentage(true);
VirtualListViewControl result = (VirtualListViewControl) tested
.createRequestControl();
assertNotNull(result);
assertEquals(OID_REQUEST, result.getID());
int expectedBeforeCount = 2;
int expectedAfterCount = 2;
// interestingly, it seems rather than calculate what 25% of 1000 is,
// the VLVControl requests 25 out of an expected 100
int expectedOffset = 25;
int expectedContentCount = 100;
assertEncodedRequest(result.getEncodedValue(), expectedBeforeCount,
expectedAfterCount, expectedOffset, expectedContentCount,
new byte[0]);
}
public void testPostProcess() throws Exception {
int pageSize = 5;
int targetOffset = 25;
int listSize = 1000;
VirtualListViewControlDirContextProcessor tested = new VirtualListViewControlDirContextProcessor(
pageSize, targetOffset, listSize,
new VirtualListViewResultsCookie(new byte[0], 0, 0));
int virtualListViewResult = 53; // unwilling to perform
byte[] encoded = encodeResponseValue(10, listSize,
virtualListViewResult);
VirtualListViewResponseControl control = new VirtualListViewResponseControl(
OID_RESPONSE, false, encoded);
ldapContextControl.expectAndDefaultReturn(ldapContextMock
.getResponseControls(), new Control[] { control });
replay();
try {
tested.postProcess(ldapContextMock);
fail("OperationNotSupportedException expected");
}
catch (OperationNotSupportedException expected) {
Throwable cause = expected.getCause();
assertEquals(javax.naming.OperationNotSupportedException.class,
cause.getClass());
assertEquals("[LDAP: error code 53 - Unwilling To Perform]", cause
.getMessage());
}
verify();
assertNotNull(tested.getCookie());
assertEquals(0, tested.getCookie().getCookie().length);
}
public void testBerDecoding() throws Exception {
int virtualListViewResult = 53; // unwilling to perform
byte[] encoded = encodeResponseValue(10, 1000, virtualListViewResult);
int expectedLength = 14;
assertEncodedResponse(encoded, expectedLength, 10, 1000, 53,
new byte[0]);
}
private byte[] encodeResponseValue(int targetPosition, int contentCount,
int virtualListViewResult) throws IOException {
// build the ASN.1 encoding
BerEncoder ber = new BerEncoder(10);
ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
ber.encodeInt(targetPosition); // list offset for the target entry
ber.encodeInt(contentCount); // server's estimate of the current
// number of entries in the list
ber.encodeInt(virtualListViewResult, Ber.ASN_ENUMERATED);
ber.encodeOctetString(new byte[0], Ber.ASN_OCTET_STR);
ber.endSeq();
return ber.getTrimmedBuf();
}
private void assertEncodedRequest(byte[] encodedValue,
int expectedBeforeCount, int expectedAfterCount,
int expectedOffset, int expectedContentCount,
byte[] expectedContextId) throws Exception {
dumpEncodedValue("VirtualListViewRequest\n", encodedValue);
BerDecoder ber = new BerDecoder(encodedValue, 0, encodedValue.length);
ber.parseSeq(null);
int actualBeforeCount = ber.parseInt();
int actualAfterCount = ber.parseInt();
byte targetType = (byte) ber.parseByte();
targetType <<= 3; // skip highest three bits
targetType >>= 3;
ber.parseLength(); // ignore
switch (targetType) {
case 0: // byOffset
int actualOffset = ber.parseInt();
int actualContentCount = ber.parseInt();
assertEquals("beforeCount,", expectedBeforeCount, actualBeforeCount);
assertEquals("afterCount,", expectedAfterCount, actualAfterCount);
assertEquals("offset,", expectedOffset, actualOffset);
assertEquals("contentCount,", expectedContentCount,
actualContentCount);
break;
case 1: // greaterThanOrEqual
throw new AssertionFailedError(
"CHOICE value greaterThanOrEqual not supported");
default:
throw new AssertionFailedError("illegal CHOICE value: "
+ targetType);
}
byte[] bs = ber.parseOctetString(Ber.ASN_OCTET_STR, null);
assertContextId(expectedContextId, bs);
}
private void assertContextId(byte[] expectedContextId,
byte[] actualContextId) {
if (expectedContextId == null && actualContextId == null) {
return;
}
if (expectedContextId == null && actualContextId != null) {
fail("expected <null>, got <" + actualContextId + ">");
}
if (expectedContextId != null && actualContextId == null) {
fail("expected <" + expectedContextId + ">, got <null>");
}
assertEquals(expectedContextId.length, actualContextId.length);
}
private void assertEncodedResponse(byte[] encodedValue,
int expectedEncodingLength, int expectedTargetPosition,
int expectedContentCount, int expectedVirtualListViewResult,
byte[] expectedContextId) throws Exception {
dumpEncodedValue("VirtualListViewResponse\n", encodedValue);
assertEquals(expectedEncodingLength, encodedValue.length);
BerDecoder ber = new BerDecoder(encodedValue, 0, encodedValue.length);
ber.parseSeq(null);
int actualTargetPosition = ber.parseInt();
int actualContentCount = ber.parseInt();
int actualVirtualListViewResult = ber.parseEnumeration();
assertEquals("targetPosition,", expectedTargetPosition,
actualTargetPosition);
assertEquals("contentCount,", expectedContentCount, actualContentCount);
assertEquals("virtualListViewResult,", expectedVirtualListViewResult,
actualVirtualListViewResult);
byte[] bs = ber.parseOctetString(Ber.ASN_OCTET_STR, null);
assertContextId(expectedContextId, bs);
}
private void dumpEncodedValue(String message, byte[] encodedValue) {
Ber.dumpBER(System.out, message, encodedValue, 0, encodedValue.length);
}
}