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]

Reply via email to