Author: rdonkin
Date: Sat Mar 29 01:02:34 2008
New Revision: 642517
URL: http://svn.apache.org/viewvc?rev=642517&view=rev
Log:
Partial FETCH processing
Added:
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElement.java
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannel.java
james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElementTest.java
james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannelTest.java
Modified:
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java
Modified:
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java?rev=642517&r1=642516&r2=642517&view=diff
==============================================================================
---
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java
(original)
+++
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/FetchProcessor.java
Sat Mar 29 01:02:34 2008
@@ -476,43 +476,70 @@
private FetchResponse.BodyElement bodyFetch(final MessageResult
messageResult,
BodyFetchElement fetchElement) throws MessagingException,
ProtocolException {
- final FetchResponse.BodyElement result;
+ final Long firstOctet = fetchElement.getFirstOctet();
+ final Long numberOfOctets = fetchElement.getNumberOfOctets();
final String name = fetchElement.getResponseName();
final int specifier = fetchElement.getSectionType();
final int[] path = fetchElement.getPath();
final Collection names = fetchElement.getFieldNames();
final boolean isBase = (path == null || path.length == 0);
+ final FetchResponse.BodyElement fullResult
+ = bodyContent(messageResult, name, specifier, path, names,
isBase);
+ final FetchResponse.BodyElement result
+ = wrapIfPartialFetch(firstOctet, numberOfOctets, fullResult);
+ return result;
+
+ }
+
+ private FetchResponse.BodyElement bodyContent(final MessageResult
messageResult, final String name, final int specifier, final int[] path, final
Collection names, final boolean isBase) throws MailboxManagerException,
MessagingException {
+ final FetchResponse.BodyElement fullResult;
switch (specifier) {
case BodyFetchElement.CONTENT:
- result = content(messageResult, name, path, isBase);
+ fullResult = content(messageResult, name, path, isBase);
break;
case BodyFetchElement.HEADER_FIELDS:
- result = fields(messageResult, name, path, names, isBase);
+ fullResult = fields(messageResult, name, path, names,
isBase);
break;
case BodyFetchElement.HEADER_NOT_FIELDS:
- result = fieldsNot(messageResult, name, path, names,
isBase);
+ fullResult = fieldsNot(messageResult, name, path, names,
isBase);
break;
case BodyFetchElement.MIME:
- result = mimeHeaders(messageResult, name, path, isBase);
+ fullResult = mimeHeaders(messageResult, name, path,
isBase);
break;
case BodyFetchElement.HEADER:
- result = headers(messageResult, name, path, isBase);
+ fullResult = headers(messageResult, name, path, isBase);
break;
case BodyFetchElement.TEXT:
- result = text(messageResult, name, path, isBase);
+ fullResult = text(messageResult, name, path, isBase);
break;
default:
- result = null;
+ fullResult = null;
break;
}
+ return fullResult;
+ }
+ private FetchResponse.BodyElement wrapIfPartialFetch(final Long
firstOctet, final Long numberOfOctets, final FetchResponse.BodyElement
fullResult) {
+ final FetchResponse.BodyElement result;
+ if (firstOctet == null) {
+ result = fullResult;
+ } else {
+ final long numberOfOctetsAsLong;
+ if (numberOfOctets == null) {
+ numberOfOctetsAsLong = Long.MAX_VALUE;
+ } else {
+ numberOfOctetsAsLong = numberOfOctets.longValue();
+ }
+ final long firstOctetAsLong = firstOctet.longValue();
+ result = new PartialFetchBodyElement(fullResult,
+ firstOctetAsLong, numberOfOctetsAsLong);
+ }
return result;
-
}
private FetchResponse.BodyElement text(final MessageResult
messageResult, String name, final int[] path, final boolean isBase) throws
MailboxManagerException {
@@ -815,7 +842,5 @@
public void writeTo(WritableByteChannel channel) throws IOException {
content.writeTo(channel);
}
-
-
}
}
Added:
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElement.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElement.java?rev=642517&view=auto
==============================================================================
---
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElement.java
(added)
+++
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElement.java
Sat Mar 29 01:02:34 2008
@@ -0,0 +1,47 @@
+package org.apache.james.imapserver.processor.imap4rev1;
+
+import java.io.IOException;
+import java.nio.channels.WritableByteChannel;
+
+import
org.apache.james.imap.message.response.imap4rev1.FetchResponse.BodyElement;
+
+/**
+ * Wraps full content to implement a partial fetch.
+ */
+final class PartialFetchBodyElement implements BodyElement {
+
+ private final BodyElement delegate;
+ private final long firstOctet;
+ private final long numberOfOctets;
+
+ public PartialFetchBodyElement(final BodyElement delegate, final long
firstOctet,
+ final long numberOfOctets) {
+ super();
+ this.delegate = delegate;
+ this.firstOctet = firstOctet;
+ this.numberOfOctets = numberOfOctets;
+ }
+
+ public String getName() {
+ return delegate.getName();
+ }
+
+ public long size() {
+ final long size = delegate.size();
+ final long numberOfOctets;
+ if (size > this.numberOfOctets) {
+ numberOfOctets = this.numberOfOctets;
+ } else {
+ numberOfOctets = size;
+ }
+ final long result = numberOfOctets - firstOctet;
+ return result;
+ }
+
+ public void writeTo(WritableByteChannel channel) throws IOException {
+ PartialWritableByteChannel partialChannel =
+ new PartialWritableByteChannel(channel, firstOctet, size());
+ delegate.writeTo(partialChannel);
+ }
+
+}
\ No newline at end of file
Added:
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannel.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannel.java?rev=642517&view=auto
==============================================================================
---
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannel.java
(added)
+++
james/server/trunk/imap-mailbox-processor-function/src/main/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannel.java
Sat Mar 29 01:02:34 2008
@@ -0,0 +1,96 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.apache.james.imapserver.processor.imap4rev1;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+/**
+ * Filters a [EMAIL PROTECTED] WritableByteChannel}
+ * to supply a limited byte range
+ */
+class PartialWritableByteChannel implements WritableByteChannel {
+
+ private final WritableByteChannel delegate;
+ private final long firstOctet;
+ private final long numberOfOctets;
+ private long bytesWritten;
+
+ public PartialWritableByteChannel(final WritableByteChannel delegate,
final long firstOctet, final long numberOfOctets) {
+ super();
+ this.delegate = delegate;
+ this.firstOctet = firstOctet;
+ this.numberOfOctets = numberOfOctets;
+ bytesWritten = 0;
+ }
+
+ public int write(ByteBuffer src) throws IOException {
+ final int result;
+ final long bytesToIgnore = firstOctet - bytesWritten;
+ if (bytesToIgnore > 0) {
+ final int remaining = src.remaining();
+ if (remaining <= bytesToIgnore) {
+ result = ignoreRemaining(src);
+ } else {
+ final int remainingBytesToIgnore = (int) bytesToIgnore;
+ src.position(src.position() + remainingBytesToIgnore);
+ result = writeRemaining(src, numberOfOctets) +
remainingBytesToIgnore;
+ }
+ } else {
+ final long bytesToWrite = numberOfOctets - bytesWritten +
firstOctet;
+ result = writeRemaining(src, bytesToWrite);
+ }
+ bytesWritten += result;
+ return result;
+ }
+
+ private int writeRemaining(ByteBuffer src, final long bytesToWrite) throws
IOException {
+ final int remaining = src.remaining();
+ final int result;
+ if (bytesToWrite <= 0) {
+ result = ignoreRemaining(src);
+ } else if (remaining < bytesToWrite ) {
+ result = delegate.write(src);
+ } else {
+ final ByteBuffer slice = src.asReadOnlyBuffer();
+ slice.limit(slice.position() + (int) bytesToWrite);
+ delegate.write(slice);
+ result = ignoreRemaining(src);
+ }
+ return result;
+ }
+
+ private int ignoreRemaining(ByteBuffer src) {
+ final int result;
+ result = src.remaining();
+ src.position(src.limit());
+ return result;
+ }
+
+ public void close() throws IOException {
+ delegate.close();
+ }
+
+ public boolean isOpen() {
+ return delegate.isOpen();
+ }
+
+}
Added:
james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElementTest.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElementTest.java?rev=642517&view=auto
==============================================================================
---
james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElementTest.java
(added)
+++
james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialFetchBodyElementTest.java
Sat Mar 29 01:02:34 2008
@@ -0,0 +1,72 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.apache.james.imapserver.processor.imap4rev1;
+
+import
org.apache.james.imap.message.response.imap4rev1.FetchResponse.BodyElement;
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
+
+public class PartialFetchBodyElementTest extends MockObjectTestCase {
+
+ private static final long NUMBER_OF_OCTETS = 100;
+
+ Mock mockBodyElement;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ mockBodyElement = mock(BodyElement.class);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testSizeShouldBeNumberOfOctetsWhenSizeMoreWhenStartIsZero()
throws Exception {
+ long moreThanNumberOfOctets = NUMBER_OF_OCTETS + 1;
+ PartialFetchBodyElement element = new
PartialFetchBodyElement((BodyElement) mockBodyElement.proxy(),
+ 0, NUMBER_OF_OCTETS);
+ mockBodyElement.expects(once()).method("size").will(returnValue(new
Long(moreThanNumberOfOctets)));
+ assertEquals("Size is more than number of octets so should be number
of octets", NUMBER_OF_OCTETS, element.size());
+ }
+
+ public void testSizeShouldBeSizeWhenNumberOfOctetsMoreWhenStartIsZero()
throws Exception {
+ long lessThanNumberOfOctets = NUMBER_OF_OCTETS -1;
+ PartialFetchBodyElement element = new
PartialFetchBodyElement((BodyElement) mockBodyElement.proxy(),
+ 0, NUMBER_OF_OCTETS);
+ mockBodyElement.expects(once()).method("size").will(returnValue(new
Long(lessThanNumberOfOctets)));
+ assertEquals("Size is less than number of octets so should be size",
lessThanNumberOfOctets, element.size());
+ }
+
+ public void
testWhenStartPlusNumberOfOctetsIsMoreThanSizeSizeShouldBeSizeMinusStart()
throws Exception {
+ long size = 60;
+ PartialFetchBodyElement element = new
PartialFetchBodyElement((BodyElement) mockBodyElement.proxy(),
+ 10, NUMBER_OF_OCTETS);
+ mockBodyElement.expects(once()).method("size").will(returnValue(new
Long(size)));
+ assertEquals("Size is less than number of octets so should be size",
50, element.size());
+ }
+
+ public void
testWhenStartPlusNumberOfOctetsIsLessThanSizeSizeShouldBeNumberOfOctetsMinusStart()
throws Exception {
+ long size = 600;
+ PartialFetchBodyElement element = new
PartialFetchBodyElement((BodyElement) mockBodyElement.proxy(),
+ 10, NUMBER_OF_OCTETS);
+ mockBodyElement.expects(once()).method("size").will(returnValue(new
Long(size)));
+ assertEquals("Size is less than number of octets so should be size",
90, element.size());
+ }
+}
Added:
james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannelTest.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannelTest.java?rev=642517&view=auto
==============================================================================
---
james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannelTest.java
(added)
+++
james/server/trunk/imap-mailbox-processor-function/src/test/java/org/apache/james/imapserver/processor/imap4rev1/PartialWritableByteChannelTest.java
Sat Mar 29 01:02:34 2008
@@ -0,0 +1,484 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.apache.james.imapserver.processor.imap4rev1;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+import junit.framework.TestCase;
+
+public class PartialWritableByteChannelTest extends TestCase implements
WritableByteChannel {
+
+ private static final int CAPACITY = 2048;
+
+ ByteBuffer sink;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ sink = ByteBuffer.allocate(CAPACITY);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testShouldPassFullBufferWhenStartZeroSizeLimit() throws
Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 0, 10);
+ assertEquals(10, channel.write(src));
+ assertEquals(10, sink.position());
+ sink.flip();
+ for (int i=0;i<10;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+
+ public void testShouldIgnoreBytesAfterLimit() throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 0, 4);
+ assertEquals(10, channel.write(src));
+ assertEquals(4, sink.position());
+ sink.flip();
+ for (int i=0;i<4;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+
+ public void testShouldIgnoreBytesBeforeStart() throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 4, 6);
+ assertEquals(10, channel.write(src));
+ assertEquals(6, sink.position());
+ sink.flip();
+ for (int i=4;i<10;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+
+ public void testShouldIgnoreBytesBeforeStartAndAfterLimit() throws
Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 4, 2);
+ assertEquals(10, channel.write(src));
+ assertEquals(2, sink.position());
+ sink.flip();
+ for (int i=4;i<6;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+
+ public void testMultiBufferShouldPassFullBufferWhenStartZeroSizeLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 0, 50);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(50, sink.position());
+ sink.flip();
+ for (int l=0;l<5;l++) {
+ for (int i=0;i<10;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+ }
+
+ public void testMultiBufferOnBoundaryShouldIgnoreBytesAfterLimit() throws
Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 0, 30);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(30, sink.position());
+ sink.flip();
+ for (int l=0;l<3;l++) {
+ for (int i=0;i<10;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+ }
+
+ public void testMultiBufferBeforeBoundaryShouldIgnoreBytesAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 0, 39);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(39, sink.position());
+ sink.flip();
+ for (int l=0;l<3;l++) {
+ for (int i=0;i<10;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+ for (int i=0;i<9;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+
+ public void testMultiBufferAfterBoundaryShouldIgnoreBytesAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 0, 31);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(31, sink.position());
+ sink.flip();
+ for (int l=0;l<3;l++) {
+ for (int i=0;i<10;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+ assertEquals(0, sink.get());
+ }
+
+ public void
testMultiBufferOnBoundaryOctetsOverBufferShouldIgnoreBytesBeforeStart() throws
Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 20, 21);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(21, sink.position());
+ sink.flip();
+ for (int l=0;l<2;l++) {
+ for (int i=0;i<10;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+ assertEquals(0, sink.get());
+ }
+
+ public void
testMultiBufferAfterBoundaryOctetsOverBufferShouldIgnoreBytesBeforeStart()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 21, 21);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(21, sink.position());
+ sink.flip();
+ for (int l=0;l<2;l++) {
+ for (int i=1;i<11;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+ assertEquals(1, sink.get());
+ }
+
+ public void
testMultiBufferBeforeBoundaryOctetsOverBufferShouldIgnoreBytesBeforeStart()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 19, 21);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(21, sink.position());
+ sink.flip();
+ for (int l=0;l<2;l++) {
+ for (int i=9;i<19;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+ assertEquals(9, sink.get());
+ }
+
+ public void
testMultiBufferOnBoundaryOctetsOnBufferShouldIgnoreBytesBeforeStart() throws
Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 20, 20);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(20, sink.position());
+ sink.flip();
+ for (int l=0;l<2;l++) {
+ for (int i=0;i<10;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+ }
+
+ public void
testMultiBufferAfterBoundaryOctetsObBufferShouldIgnoreBytesBeforeStart() throws
Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 21, 20);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(20, sink.position());
+ sink.flip();
+ for (int l=0;l<2;l++) {
+ for (int i=1;i<11;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+ }
+
+ public void
testMultiBufferBeforeBoundaryOctetsOnBufferShouldIgnoreBytesBeforeStart()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 19, 20);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(20, sink.position());
+ sink.flip();
+ for (int l=0;l<2;l++) {
+ for (int i=9;i<19;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+ }
+
+ public void
testMultiBufferOnBoundaryOctetsUnderBufferShouldIgnoreBytesBeforeStart() throws
Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 20, 19);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(19, sink.position());
+ sink.flip();
+ for (int l=0;l<2;l++) {
+ for (int i=0;i<10;i++) {
+ if (sink.hasRemaining()) {
+ assertEquals(i, sink.get());
+ }
+ }
+ }
+ }
+
+ public void
testMultiBufferAfterBoundaryOctetsUnderBufferShouldIgnoreBytesBeforeStart()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 21, 19);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(19, sink.position());
+ sink.flip();
+ for (int l=0;l<2;l++) {
+ for (int i=1;i<11;i++) {
+ if (sink.hasRemaining()) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+ }
+ }
+
+ public void
testMultiBufferBeforeBoundaryOctetsUnderBufferShouldIgnoreBytesBeforeStart()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 19, 19);
+ for (int i=0;i<5;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(19, sink.position());
+ sink.flip();
+ for (int l=0;l<2;l++) {
+ for (int i=9;i<19;i++) {
+ if (sink.hasRemaining()) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+ }
+ }
+
+ public void testMultiBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 4, 2);
+ assertEquals(10, channel.write(src));
+ assertEquals(2, sink.position());
+ sink.flip();
+ for (int i=4;i<6;i++) {
+ assertEquals(i, sink.get());
+ }
+ }
+
+ public void
testMultiBufferOnBoundaryOnBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 30, 30);
+ for (int i=0;i<8;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(30, sink.position());
+ sink.flip();
+ for (int i=0;i<30;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+
+ public void
testMultiBufferBeforeBoundaryOnBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 29, 30);
+ for (int i=0;i<8;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(30, sink.position());
+ sink.flip();
+ for (int i=9;i<39;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+
+ public void
testMultiBufferAfterBoundaryOnBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 31, 30);
+ for (int i=0;i<8;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(30, sink.position());
+ sink.flip();
+ for (int i=1;i<31;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+
+ public void
testMultiBufferOnBoundaryAfterBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 30, 31);
+ for (int i=0;i<8;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(31, sink.position());
+ sink.flip();
+ for (int i=0;i<31;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+
+ public void
testMultiBufferBeforeBoundaryAfterBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 29, 31);
+ for (int i=0;i<8;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(31, sink.position());
+ sink.flip();
+ for (int i=9;i<40;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+
+ public void
testMultiBufferAfterBoundaryAfterBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 31, 31);
+ for (int i=0;i<8;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(31, sink.position());
+ sink.flip();
+ for (int i=1;i<32;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+
+ public void
testMultiBufferOnBoundaryBeforeBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 30, 29);
+ for (int i=0;i<8;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(29, sink.position());
+ sink.flip();
+ for (int i=0;i<29;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+
+ public void
testMultiBufferBeforeBoundaryBeforeBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 29, 29);
+ for (int i=0;i<8;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(29, sink.position());
+ sink.flip();
+ for (int i=9;i<38;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+
+ public void
testMultiBufferAfterBoundaryBeforeBufferShouldIgnoreBytesBeforeStartAndAfterLimit()
throws Exception {
+ byte [] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteBuffer src = ByteBuffer.wrap(bytes);
+ PartialWritableByteChannel channel = new
PartialWritableByteChannel(this, 31, 29);
+ for (int i=0;i<8;i++) {
+ assertEquals(10, channel.write(src));
+ src.rewind();
+ }
+ assertEquals(29, sink.position());
+ sink.flip();
+ for (int i=1;i<30;i++) {
+ assertEquals(i % 10, sink.get());
+ }
+ }
+
+ public int write(ByteBuffer src) throws IOException {
+ int result = src.remaining();
+ sink.put(src);
+ return result;
+ }
+
+ public void close() throws IOException {
+ }
+
+ public boolean isOpen() {
+ return true;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]