hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r454135 - in /jakarta/httpcomponents/httpcore/trunk/module-nio/src: examples/org/apache/http/nio/examples/ main/java/org/apache/http/nio/impl/ test/java/org/apache/http/nio/impl/ test/java/org/apache/http/nio/mockup/
Date Sun, 08 Oct 2006 12:34:29 GMT
Author: olegk
Date: Sun Oct  8 05:34:28 2006
New Revision: 454135

URL: http://svn.apache.org/viewvc?view=rev&rev=454135
Log:
Major rewrite of the NIO buffering primitives.

Chanelog:
=========
* Session input / output buffers can now be asynchronously read from and filled up from a channel/ written to and flushed to channel. 
* Session buffers can automatically expand to accommodate incoming or outgoing data without blocking. 
* Session buffers can be wrapped with a HTTP data receiver / transmitter in order to emulate synchronous I/O.

Added:
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/ExpandableBuffer.java   (with props)
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionInputBuffer.java
      - copied, changed from r450187, jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataReceiver.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionOutputBuffer.java
      - copied, changed from r450187, jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataTransmitter.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestSessionBuffers.java   (with props)
Modified:
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncEchoServer.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpClientConnection.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataReceiver.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataTransmitter.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpServerConnection.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataReceiver.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataTransmitter.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestAllImpl.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataReceiverMockup.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataTransmitterMockup.java

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncEchoServer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncEchoServer.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncEchoServer.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncEchoServer.java Sun Oct  8 05:34:28 2006
@@ -13,6 +13,8 @@
 import org.apache.http.nio.impl.DefaultIOReactor;
 import org.apache.http.nio.impl.AsyncHttpDataReceiver;
 import org.apache.http.nio.impl.AsyncHttpDataTransmitter;
+import org.apache.http.nio.impl.SessionInputBuffer;
+import org.apache.http.nio.impl.SessionOutputBuffer;
 import org.apache.http.params.HttpParams;
 
 public class AsyncEchoServer {
@@ -41,9 +43,11 @@
         public void connected(IOSession session) {
             System.out.println("connected");
             
-            AsyncHttpDataReceiver datareceiver = new AsyncHttpDataReceiver(session, 2048);
+            SessionInputBuffer inbuf = new SessionInputBuffer(2048, 512); 
+            AsyncHttpDataReceiver datareceiver = new AsyncHttpDataReceiver(session, inbuf);
             session.setAttribute(CONSUMER, datareceiver);
-            AsyncHttpDataTransmitter datatransmitter = new AsyncHttpDataTransmitter(session, 2048);
+            SessionOutputBuffer outbuf = new SessionOutputBuffer(2048, 512); 
+            AsyncHttpDataTransmitter datatransmitter = new AsyncHttpDataTransmitter(session, outbuf);
             session.setAttribute(PRODUCER, datatransmitter);
             
             Thread worker = new WorkerThread(session, datareceiver, datatransmitter);

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpClientConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpClientConnection.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpClientConnection.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpClientConnection.java Sun Oct  8 05:34:28 2006
@@ -58,12 +58,17 @@
         }
         this.session = session;
         int buffersize = HttpConnectionParams.getSocketBufferSize(params);
+        int linebuffersize = buffersize;
+        if (linebuffersize > 512) {
+            linebuffersize = 512;
+        }
         
-        AsyncHttpDataReceiver datareceiver = new AsyncHttpDataReceiver(
-                session, buffersize);
+        SessionInputBuffer inbuf = new SessionInputBuffer(buffersize, linebuffersize); 
+        AsyncHttpDataReceiver datareceiver = new AsyncHttpDataReceiver(session, inbuf);
         datareceiver.reset(params);
-        AsyncHttpDataTransmitter datatransmitter = new AsyncHttpDataTransmitter(
-                session, buffersize);
+        
+        SessionOutputBuffer outbuf = new SessionOutputBuffer(buffersize, linebuffersize); 
+        AsyncHttpDataTransmitter datatransmitter = new AsyncHttpDataTransmitter(session, outbuf);
         datatransmitter.reset(params);
 
         this.ioConsumer = datareceiver;

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataReceiver.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataReceiver.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataReceiver.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataReceiver.java Sun Oct  8 05:34:28 2006
@@ -29,7 +29,6 @@
 package org.apache.http.nio.impl;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 
 import org.apache.http.io.CharArrayBuffer;
 import org.apache.http.nio.EventMask;
@@ -45,23 +44,20 @@
     private volatile boolean closed = false;
     private volatile IOException exception = null;
     
-    public AsyncHttpDataReceiver(final IOSession session, int buffersize) {
-        super();
+    public AsyncHttpDataReceiver(
+            final IOSession session, 
+            final SessionInputBuffer buffer) {
+        super(buffer);
         if (session == null) {
             throw new IllegalArgumentException("I/O session may not be null");
         }
         this.session = session;
         this.mutex = new Object();
-        int linebuffersize = buffersize;
-        if (linebuffersize > 512) {
-            linebuffersize = 512;
-        }
-        initBuffer(buffersize, linebuffersize);
     }
     
     public void consumeInput() throws IOException {
         synchronized (this.mutex) {
-            int noRead = this.session.channel().read(getBuffer());
+            int noRead = getBuffer().fill(this.session.channel());
             if (noRead == -1) {
                 this.closed = true;
             }
@@ -72,14 +68,13 @@
         }
     }
     
-    protected int fillBuffer() throws IOException {
+    protected int waitForData() throws IOException {
         if (this.closed) {
             return -1;
         }
         synchronized (this.mutex) {
-            ByteBuffer buffer = getBuffer();
             try {
-                while (buffer.position() == 0 && !this.closed) {
+                while (!getBuffer().hasData() && !this.closed) {
                     this.session.setEvent(EventMask.READ);
                     this.mutex.wait();
                 }
@@ -92,7 +87,7 @@
                 if (this.closed) {
                     return -1;
                 } else {
-                    return buffer.position();
+                    return getBuffer().length();
                 }
                 
             } catch (InterruptedException ex) {
@@ -106,8 +101,7 @@
             return false;
         }
         synchronized (this.mutex) {
-            ByteBuffer buffer = getBuffer();
-            if (buffer.position() > 0) {
+            if (getBuffer().hasData()) {
                 return true;
             }
             try {
@@ -118,7 +112,7 @@
             if (this.closed) {
                 return false;
             }
-            return buffer.position() > 0;
+            return getBuffer().hasData();
         }
     }
     

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataTransmitter.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataTransmitter.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataTransmitter.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpDataTransmitter.java Sun Oct  8 05:34:28 2006
@@ -29,7 +29,6 @@
 package org.apache.http.nio.impl;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 
 import org.apache.http.io.CharArrayBuffer;
 import org.apache.http.nio.EventMask;
@@ -45,25 +44,21 @@
     private volatile boolean closed = false;
     private volatile IOException exception = null;
     
-    public AsyncHttpDataTransmitter(final IOSession session, int buffersize) {
-        super();
+    public AsyncHttpDataTransmitter(
+            final IOSession session,
+            final SessionOutputBuffer buffer) {
+        super(buffer);
         if (session == null) {
             throw new IllegalArgumentException("I/O session may not be null");
         }
         this.session = session;
         this.mutex = new Object();
-        int linebuffersize = buffersize;
-        if (linebuffersize > 512) {
-            linebuffersize = 512;
-        }
-        initBuffer(buffersize, linebuffersize);
     }
 
     public void produceOutput() throws IOException {
         synchronized (this.mutex) {
-            ByteBuffer buffer = getBuffer();
-            this.session.channel().write(buffer);
-            if (!buffer.hasRemaining()) {
+            getBuffer().flush(this.session.channel());
+            if (!getBuffer().hasData()) {
                 this.session.clearEvent(EventMask.WRITE);
                 this.mutex.notifyAll();            
             }
@@ -76,9 +71,8 @@
         }
         this.session.setEvent(EventMask.WRITE);
         synchronized (this.mutex) {
-            ByteBuffer buffer = getBuffer();
             try {
-                while (buffer.hasRemaining() && !this.closed) {
+                while (getBuffer().hasData() && !this.closed) {
                     this.mutex.wait();
                 }
 

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpServerConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpServerConnection.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpServerConnection.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/AsyncHttpServerConnection.java Sun Oct  8 05:34:28 2006
@@ -56,12 +56,17 @@
         }
         this.session = session;
         int buffersize = HttpConnectionParams.getSocketBufferSize(params);
+        int linebuffersize = buffersize;
+        if (linebuffersize > 512) {
+            linebuffersize = 512;
+        }
         
-        AsyncHttpDataReceiver datareceiver = new AsyncHttpDataReceiver(
-                session, buffersize);
+        SessionInputBuffer inbuf = new SessionInputBuffer(buffersize, linebuffersize); 
+        AsyncHttpDataReceiver datareceiver = new AsyncHttpDataReceiver(session, inbuf);
         datareceiver.reset(params);
-        AsyncHttpDataTransmitter datatransmitter = new AsyncHttpDataTransmitter(
-                session, buffersize);
+        
+        SessionOutputBuffer outbuf = new SessionOutputBuffer(buffersize, linebuffersize); 
+        AsyncHttpDataTransmitter datatransmitter = new AsyncHttpDataTransmitter(session, outbuf);
         datatransmitter.reset(params);
 
         this.ioConsumer = datareceiver;

Added: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/ExpandableBuffer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/ExpandableBuffer.java?view=auto&rev=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/ExpandableBuffer.java (added)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/ExpandableBuffer.java Sun Oct  8 05:34:28 2006
@@ -0,0 +1,105 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ *  Copyright 1999-2006 The Apache Software Foundation
+ *
+ *  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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.nio.impl;
+
+import java.nio.ByteBuffer;
+
+public class ExpandableBuffer {
+    
+    public final static int INPUT_MODE = 0;
+    public final static int OUTPUT_MODE = 1;
+    
+    private int mode;
+    protected ByteBuffer buffer = null;
+
+    public ExpandableBuffer(int buffersize) {
+        super();
+        this.buffer = ByteBuffer.allocateDirect(buffersize);
+        this.mode = INPUT_MODE;
+    }
+
+    protected int getMode() {
+        return this.mode;
+    }
+    
+    protected void setOutputMode() {
+        if (this.mode != OUTPUT_MODE) {
+            this.buffer.flip();
+            this.mode = OUTPUT_MODE;
+        }
+    }
+    
+    protected void setInputMode() {
+        if (this.mode != INPUT_MODE) {
+            if (this.buffer.hasRemaining()) {
+                this.buffer.compact();
+            } else {
+                this.buffer.clear();
+            }
+            this.mode = INPUT_MODE;
+        }
+    }
+    
+    private void expandCapacity(int capacity) {
+        ByteBuffer oldbuffer = this.buffer;
+        this.buffer = ByteBuffer.allocateDirect(capacity);
+        oldbuffer.flip();
+        this.buffer.put(oldbuffer);
+    }
+    
+    protected void expand() {
+        int newcapacity = (this.buffer.capacity() + 1) << 1;
+        if (newcapacity < 0) {
+            newcapacity = Integer.MAX_VALUE;
+        }
+        expandCapacity(newcapacity);
+    }
+    
+    protected void ensureCapacity(int requiredCapacity) {
+        if (requiredCapacity > this.buffer.capacity()) {
+            expandCapacity(requiredCapacity);
+        }
+    }
+    
+    public int capacity() {
+        return this.buffer.capacity();
+    }
+ 
+    public boolean hasData() {
+        setOutputMode();
+        return this.buffer.hasRemaining();
+    }
+    
+    public int length() {
+        setOutputMode();
+        return this.buffer.remaining();
+    }
+        
+}

Propchange: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/ExpandableBuffer.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/ExpandableBuffer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataReceiver.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataReceiver.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataReceiver.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataReceiver.java Sun Oct  8 05:34:28 2006
@@ -30,19 +30,10 @@
 package org.apache.http.nio.impl;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
 
 import org.apache.http.io.CharArrayBuffer;
 import org.apache.http.io.HttpDataReceiver;
-import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpProtocolParams;
-import org.apache.http.protocol.HTTP;
 
 /**
  * Abstract data receiver implementation based on <code>java.nio</code>.
@@ -57,65 +48,38 @@
  */
 public abstract class NIOHttpDataReceiver implements HttpDataReceiver {
 
-    private ByteBuffer buffer = null;
+    private SessionInputBuffer buffer = null;
     
-    private Charset charset = null;
-    private CharsetDecoder chardecoder = null;
-    private CharBuffer chbuffer = null;
-    
-    private int maxLineLen = -1;
-    
-    protected void initBuffer(int buffersize, int linebuffersize) {
-        this.buffer = ByteBuffer.allocateDirect(buffersize);
-        this.buffer.flip();
-        this.charset = Charset.forName("US-ASCII");
-        this.chardecoder = createCharDecoder();
-        this.chbuffer = CharBuffer.allocate(linebuffersize);
-    }
-
-    public void reset(final HttpParams params) {
-        this.charset = Charset.forName(HttpProtocolParams.getHttpElementCharset(params)); 
-        this.chardecoder = createCharDecoder();
-        this.maxLineLen = params.getIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, -1);
-    }
-
-    private CharsetDecoder createCharDecoder() {
-        CharsetDecoder chardecoder = this.charset.newDecoder();
-        chardecoder.onMalformedInput(CodingErrorAction.REPLACE); 
-        chardecoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
-        return chardecoder;
+    protected NIOHttpDataReceiver(final SessionInputBuffer buffer) {
+        super();
+        if (buffer == null) {
+            throw new IllegalArgumentException("Session input buffer may not be null");
+        }
+        this.buffer = buffer;
     }
     
-    private int doFillBuffer() throws IOException {
-        this.buffer.compact();
-        int i = fillBuffer();
-        this.buffer.flip();
-        return i;
+    protected SessionInputBuffer getBuffer() {
+        return this.buffer;
     }
 
-    protected ByteBuffer getBuffer() {
-        return this.buffer;
+    public void reset(final HttpParams params) {
+        this.buffer.reset(params);
     }
-    
-    protected abstract int fillBuffer() throws IOException;
+
+    protected abstract int waitForData() throws IOException;
     
     public int read(final byte[] b, int off, int len) throws IOException {
         if (b == null) {
             return 0;
         }
         int noRead = 0;
-        if (!this.buffer.hasRemaining()) {
-            noRead = doFillBuffer();
+        if (!this.buffer.hasData()) {
+            noRead = waitForData();
             if (noRead == -1) {
                 return -1; 
             }
         }
-        int chunk = len;
-        if (chunk > this.buffer.remaining()) {
-            chunk = this.buffer.remaining();
-        }
-        this.buffer.get(b, off, chunk);
-        return chunk;
+        return this.buffer.read(b, off, len);
     }
     
     public int read(final byte[] b) throws IOException {
@@ -127,109 +91,36 @@
     
     public int read() throws IOException {
         int noRead = 0;
-        if (!this.buffer.hasRemaining()) {
-            noRead = doFillBuffer();
+        if (!this.buffer.hasData()) {
+            noRead = waitForData();
             if (noRead == -1) {
                 return -1; 
             }
         }
-        return this.buffer.get() & 0xff;
-    }
-    
-    private int locateLF() {
-        for (int i = this.buffer.position(); i < this.buffer.limit(); i++) {
-            int b = this.buffer.get(i);
-            if (b == HTTP.LF) {
-                return i;
-            }
-        }
-        return -1;
+        return this.buffer.read() & 0xff;
     }
     
     public int readLine(final CharArrayBuffer charbuffer) throws IOException {
         if (charbuffer == null) {
             throw new IllegalArgumentException("Char array buffer may not be null");
         }
+        int len = charbuffer.length();
         int noRead = 0;
-        this.chbuffer.clear();
-        this.chardecoder.reset();
-        boolean retry = true;
-        while (retry) {
-            // attempt to find end of line (LF)
-            int i = locateLF(); 
-            if (i != -1) {
-                // end of line found. 
-                retry = false;
-                // read up to the end of line
-                int origLimit = this.buffer.limit();
-                this.buffer.limit(i + 1);
-                for (;;) {
-                    CoderResult result = this.chardecoder.decode(
-                    		this.buffer, this.chbuffer, true);
-                    if (result.isOverflow()) {
-                        this.chbuffer.flip();
-                        charbuffer.append(this.chbuffer.array(), 
-                        		this.chbuffer.position(), this.chbuffer.remaining());
-                        this.chbuffer.clear();
-                    }
-                    if (result.isUnderflow()) {
-                        break;
-                    }
-                }
-                this.buffer.limit(origLimit);
-            } else {
-                // end of line not found
-                if (this.buffer.hasRemaining()) {
-                    // decode the entire buffer content
-                    this.chardecoder.decode(this.buffer, this.chbuffer, false);
-                }
-                // discard the decoded content
-                noRead = doFillBuffer();
-                if (noRead == -1) {
-                    retry = false;
-                    // terminate the decoding process
-                    this.chardecoder.decode(this.buffer, this.chbuffer, true);
-                }
-            }
-            // append the decoded content to the line buffer
-            this.chbuffer.flip();
-            if (this.chbuffer.hasRemaining()) {
-                charbuffer.append(this.chbuffer.array(), 
-                		this.chbuffer.position(), this.chbuffer.remaining());
+        boolean endOfStream = false;
+        while (!this.buffer.readLine(charbuffer, endOfStream)) {
+            if (endOfStream) {
+                break;
             }
-            this.chbuffer.clear();
-            if (this.maxLineLen > 0 && charbuffer.length() >= this.maxLineLen) {
-                throw new IOException("Maximum line length limit exceeded");
+            noRead = waitForData();
+            if (noRead == -1) {
+                endOfStream = true; 
             }
         }
-        // flush the decoder
-        this.chardecoder.flush(this.chbuffer);
-        this.chbuffer.flip();
-        // append the decoded content to the line buffer
-        if (this.chbuffer.hasRemaining()) {
-            charbuffer.append(this.chbuffer.array(), 
-            		this.chbuffer.position(), this.chbuffer.remaining());
-        }
-        if (noRead == -1 && charbuffer.length() == 0) {
-            // indicate the end of stream
+        int total = charbuffer.length() - len;
+        if (total == 0 && endOfStream) {
             return -1;
-        }
-        // discard LF if found
-        int l = charbuffer.length(); 
-        if (l > 0) {
-            if (charbuffer.charAt(l - 1) == HTTP.LF) {
-                l--;
-                charbuffer.setLength(l);
-            }
-            // discard CR if found
-            if (l > 0) {
-                if (charbuffer.charAt(l - 1) == HTTP.CR) {
-                    l--;
-                    charbuffer.setLength(l);
-                }
-            }
-        }
-        return l;
+        } else 
+            return total;
     }
     
     public String readLine() throws IOException {

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataTransmitter.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataTransmitter.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataTransmitter.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataTransmitter.java Sun Oct  8 05:34:28 2006
@@ -30,17 +30,10 @@
 package org.apache.http.nio.impl;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
 
 import org.apache.http.io.CharArrayBuffer;
 import org.apache.http.io.HttpDataTransmitter;
 import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpProtocolParams;
 import org.apache.http.protocol.HTTP;
 
 /**
@@ -58,136 +51,46 @@
 
     private static final byte[] CRLF = new byte[] {HTTP.CR, HTTP.LF};
 
-    private ByteBuffer buffer = null;
+    private SessionOutputBuffer buffer = null;
 
-    private Charset charset = null;
-    private CharsetEncoder charencoder = null;
-    private CharBuffer chbuffer = null;
-
-    protected void initBuffer(int buffersize, int linebuffersize) {
-        this.buffer = ByteBuffer.allocateDirect(buffersize);
-        this.charset = Charset.forName("US-ASCII");
-        this.charencoder = createCharEncoder();
-        this.chbuffer = CharBuffer.allocate(linebuffersize);
+    public NIOHttpDataTransmitter(final SessionOutputBuffer buffer) {
+        super();
+        if (buffer == null) {
+            throw new IllegalArgumentException("Session output buffer may not be null");
+        }
+        this.buffer = buffer;
     }
     
-    public void reset(final HttpParams params) {
-        this.charset = Charset.forName(HttpProtocolParams.getHttpElementCharset(params)); 
-        this.charencoder = createCharEncoder();
+    protected SessionOutputBuffer getBuffer() {
+        return this.buffer;
     }
 
-    private void doFlushBuffer() throws IOException {
-        this.buffer.flip();
-        flushBuffer();
-        this.buffer.compact();
-    }
-    
-    protected ByteBuffer getBuffer() {
-        return this.buffer;
+    public void reset(final HttpParams params) {
+        this.buffer.reset(params);
     }
-    
+
     protected abstract void flushBuffer() throws IOException;
     
     public  void flush() throws IOException {
-        this.buffer.flip();
-        while (this.buffer.hasRemaining()) {
+        while (this.buffer.hasData()) {
             flushBuffer();
         }
-        this.buffer.clear();
-    }
-    
-    private CharsetEncoder createCharEncoder() {
-        CharsetEncoder charencoder = this.charset.newEncoder();
-        charencoder.onMalformedInput(CodingErrorAction.REPLACE); 
-        charencoder.onUnmappableCharacter(CodingErrorAction.REPLACE); 
-        return charencoder; 
     }
     
     public void write(final byte[] b, int off, int len) throws IOException {
-        if (b == null) {
-            return;
-        }
-        int remaining = len;
-        while (remaining > 0) {
-            if (this.buffer.hasRemaining()) {
-                int chunk = len;
-                if (chunk > remaining) {
-                    chunk = remaining;
-                }
-                if (chunk > this.buffer.remaining()) {
-                    chunk = this.buffer.remaining();
-                }
-                this.buffer.put(b, off, chunk);
-                off += chunk;
-                remaining -= chunk; 
-            } else {
-                doFlushBuffer();
-            }
-        }
+        this.buffer.write(b, off, len);
     }
 
     public void write(final byte[] b) throws IOException {
-        if (b == null) {
-            return;
-        }
-        write(b, 0, b.length);
-    }
-
-    private void writeCRLF() throws IOException {
-        write(CRLF);
+        this.buffer.write(b);
     }
 
     public void write(int b) throws IOException {
-        if (!this.buffer.hasRemaining()) {
-            doFlushBuffer();
-        }
-        this.buffer.put((byte)b);
+        this.buffer.write(b);
     }
 
     public void writeLine(final CharArrayBuffer buffer) throws IOException {
-        if (buffer == null) {
-            return;
-        }
-        // Do not bother if the buffer is empty
-        if (buffer.length() > 0 ) {
-        	this.charencoder.reset();
-            // transfer the string in small chunks
-            int remaining = buffer.length();
-            int offset = 0;
-            while (remaining > 0) {
-                int l = this.chbuffer.remaining();
-                boolean eol = false;
-                if (remaining < l) {
-                    l = remaining;
-                    // terminate the encoding process
-                    eol = true;
-                }
-                this.chbuffer.put(buffer.buffer(), offset, l);
-                this.chbuffer.flip();
-                
-                boolean retry = true;
-                while (retry) {
-                    CoderResult result = this.charencoder.encode(this.chbuffer, this.buffer, eol);
-                    if (result.isOverflow()) {
-                        doFlushBuffer();
-                    }
-                    retry = !result.isUnderflow();
-                }
-                this.chbuffer.compact();
-                offset += l;
-                remaining -= l;
-            }
-            // flush the encoder
-            boolean retry = true;
-            while (retry) {
-                CoderResult result = this.charencoder.flush(this.buffer);
-                if (result.isOverflow()) {
-                    doFlushBuffer();
-                }
-                retry = !result.isUnderflow();
-            }
-        }
-        writeCRLF();
+        this.buffer.writeLine(buffer);
     }
 
     public void writeLine(final String s) throws IOException {

Copied: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionInputBuffer.java (from r450187, jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataReceiver.java)
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionInputBuffer.java?view=diff&rev=454135&p1=jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataReceiver.java&r1=450187&p2=jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionInputBuffer.java&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataReceiver.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionInputBuffer.java Sun Oct  8 05:34:28 2006
@@ -30,86 +30,55 @@
 package org.apache.http.nio.impl;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
 
 import org.apache.http.io.CharArrayBuffer;
-import org.apache.http.io.HttpDataReceiver;
 import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
 import org.apache.http.protocol.HTTP;
 
-/**
- * Abstract data receiver implementation based on <code>java.nio</code>.
- *
- * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
- *
- *
- * <!-- empty lines above to avoid 'svn diff' context problems -->
- * @version $Revision$
- * 
- * @since 4.0
- */
-public abstract class NIOHttpDataReceiver implements HttpDataReceiver {
-
-    private ByteBuffer buffer = null;
+public class SessionInputBuffer extends ExpandableBuffer {
     
+    private CharBuffer charbuffer = null;
     private Charset charset = null;
     private CharsetDecoder chardecoder = null;
-    private CharBuffer chbuffer = null;
-    
     private int maxLineLen = -1;
     
-    protected void initBuffer(int buffersize, int linebuffersize) {
-        this.buffer = ByteBuffer.allocateDirect(buffersize);
-        this.buffer.flip();
+    public SessionInputBuffer(int buffersize, int linebuffersize) {
+        super(buffersize);
+        this.charbuffer = CharBuffer.allocate(linebuffersize);
         this.charset = Charset.forName("US-ASCII");
-        this.chardecoder = createCharDecoder();
-        this.chbuffer = CharBuffer.allocate(linebuffersize);
+        this.chardecoder = this.charset.newDecoder();
     }
 
     public void reset(final HttpParams params) {
         this.charset = Charset.forName(HttpProtocolParams.getHttpElementCharset(params)); 
-        this.chardecoder = createCharDecoder();
+        this.chardecoder = this.charset.newDecoder();
         this.maxLineLen = params.getIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, -1);
     }
 
-    private CharsetDecoder createCharDecoder() {
-        CharsetDecoder chardecoder = this.charset.newDecoder();
-        chardecoder.onMalformedInput(CodingErrorAction.REPLACE); 
-        chardecoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
-        return chardecoder;
-    }
-    
-    private int doFillBuffer() throws IOException {
-        this.buffer.compact();
-        int i = fillBuffer();
-        this.buffer.flip();
-        return i;
-    }
-
-    protected ByteBuffer getBuffer() {
-        return this.buffer;
+    public int fill(final ReadableByteChannel channel) throws IOException {
+        if (channel == null) {
+            throw new IllegalArgumentException("Channel may not be null");
+        }
+        setInputMode();
+        if (!this.buffer.hasRemaining()) {
+            expand();
+        }
+        int readNo = channel.read(this.buffer);
+        return readNo;
     }
     
-    protected abstract int fillBuffer() throws IOException;
-    
     public int read(final byte[] b, int off, int len) throws IOException {
         if (b == null) {
             return 0;
-        }
-        int noRead = 0;
-        if (!this.buffer.hasRemaining()) {
-            noRead = doFillBuffer();
-            if (noRead == -1) {
-                return -1; 
-            }
-        }
+        };
+        setOutputMode();
         int chunk = len;
         if (chunk > this.buffer.remaining()) {
             chunk = this.buffer.remaining();
@@ -122,124 +91,97 @@
         if (b == null) {
             return 0;
         }
+        setOutputMode();
         return read(b, 0, b.length);
     }
     
     public int read() throws IOException {
-        int noRead = 0;
-        if (!this.buffer.hasRemaining()) {
-            noRead = doFillBuffer();
-            if (noRead == -1) {
-                return -1; 
-            }
-        }
+        setOutputMode();
         return this.buffer.get() & 0xff;
     }
     
-    private int locateLF() {
+    public boolean readLine(final CharArrayBuffer linebuffer, boolean endOfStream) 
+            throws IOException {
+        setOutputMode();
+        // See if there is LF char present in the buffer
+        int pos = -1;
+        boolean hasLine = false;
         for (int i = this.buffer.position(); i < this.buffer.limit(); i++) {
             int b = this.buffer.get(i);
             if (b == HTTP.LF) {
-                return i;
+                hasLine = true;
+                pos = i + 1;
+                break;
             }
         }
-        return -1;
-    }
-    
-    public int readLine(final CharArrayBuffer charbuffer) throws IOException {
-        if (charbuffer == null) {
-            throw new IllegalArgumentException("Char array buffer may not be null");
-        }
-        int noRead = 0;
-        this.chbuffer.clear();
-        this.chardecoder.reset();
-        boolean retry = true;
-        while (retry) {
-            // attempt to find end of line (LF)
-            int i = locateLF(); 
-            if (i != -1) {
-                // end of line found. 
-                retry = false;
-                // read up to the end of line
-                int origLimit = this.buffer.limit();
-                this.buffer.limit(i + 1);
-                for (;;) {
-                    CoderResult result = this.chardecoder.decode(
-                    		this.buffer, this.chbuffer, true);
-                    if (result.isOverflow()) {
-                        this.chbuffer.flip();
-                        charbuffer.append(this.chbuffer.array(), 
-                        		this.chbuffer.position(), this.chbuffer.remaining());
-                        this.chbuffer.clear();
-                    }
-                    if (result.isUnderflow()) {
-                        break;
-                    }
-                }
-                this.buffer.limit(origLimit);
+        if (!hasLine) {
+            if (endOfStream && this.buffer.hasRemaining()) {
+                // No more data. Get the rest
+                pos = this.buffer.limit();
             } else {
-                // end of line not found
-                if (this.buffer.hasRemaining()) {
-                    // decode the entire buffer content
-                    this.chardecoder.decode(this.buffer, this.chbuffer, false);
-                }
-                // discard the decoded content
-                noRead = doFillBuffer();
-                if (noRead == -1) {
-                    retry = false;
-                    // terminate the decoding process
-                    this.chardecoder.decode(this.buffer, this.chbuffer, true);
+                if (this.maxLineLen > 0 && this.buffer.remaining() >= this.maxLineLen) {
+                    throw new IOException("Maximum line length limit exceeded");
                 }
+                // Either no complete line present in the buffer 
+                // or no more data is expected
+                return false;
             }
-            // append the decoded content to the line buffer
-            this.chbuffer.flip();
-            if (this.chbuffer.hasRemaining()) {
-                charbuffer.append(this.chbuffer.array(), 
-                		this.chbuffer.position(), this.chbuffer.remaining());
-            }
-            this.chbuffer.clear();
-            if (this.maxLineLen > 0 && charbuffer.length() >= this.maxLineLen) {
-                throw new IOException("Maximum line length limit exceeded");
+        }
+        int origLimit = this.buffer.limit();
+        this.buffer.limit(pos);
+
+        int len = this.buffer.limit() - this.buffer.position();
+        // Ensure capacity of len assuming ASCII as the most likely charset
+        linebuffer.ensureCapacity(len);
+        
+        this.chardecoder.reset();
+        
+        for (;;) {
+            CoderResult result = this.chardecoder.decode(
+                    this.buffer, 
+                    this.charbuffer, 
+                    true);
+            if (result.isOverflow()) {
+                this.charbuffer.flip();
+                linebuffer.append(
+                        this.charbuffer.array(), 
+                        this.charbuffer.position(), 
+                        this.charbuffer.remaining());
+                this.charbuffer.clear();
+            }
+            if (result.isUnderflow()) {
+                break;
             }
         }
+        this.buffer.limit(origLimit);
+
         // flush the decoder
-        this.chardecoder.flush(this.chbuffer);
-        this.chbuffer.flip();
+        this.chardecoder.flush(this.charbuffer);
+        this.charbuffer.flip();
         // append the decoded content to the line buffer
-        if (this.chbuffer.hasRemaining()) {
-            charbuffer.append(this.chbuffer.array(), 
-            		this.chbuffer.position(), this.chbuffer.remaining());
-        }
-        if (noRead == -1 && charbuffer.length() == 0) {
-            // indicate the end of stream
-            return -1;
+        if (this.charbuffer.hasRemaining()) {
+            linebuffer.append(
+                    this.charbuffer.array(), 
+                    this.charbuffer.position(), 
+                    this.charbuffer.remaining());
         }
+        
         // discard LF if found
-        int l = charbuffer.length(); 
+        int l = linebuffer.length(); 
         if (l > 0) {
-            if (charbuffer.charAt(l - 1) == HTTP.LF) {
+            if (linebuffer.charAt(l - 1) == HTTP.LF) {
                 l--;
-                charbuffer.setLength(l);
+                linebuffer.setLength(l);
             }
             // discard CR if found
             if (l > 0) {
-                if (charbuffer.charAt(l - 1) == HTTP.CR) {
+                if (linebuffer.charAt(l - 1) == HTTP.CR) {
                     l--;
-                    charbuffer.setLength(l);
+                    linebuffer.setLength(l);
                 }
             }
         }
-        return l;
+        return true;
     }
     
-    public String readLine() throws IOException {
-        CharArrayBuffer charbuffer = new CharArrayBuffer(64);
-        int l = readLine(charbuffer);
-        if (l != -1) {
-            return charbuffer.toString();
-        } else {
-            return null;
-        }
-    }
-        
 }

Copied: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionOutputBuffer.java (from r450187, jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataTransmitter.java)
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionOutputBuffer.java?view=diff&rev=454135&p1=jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataTransmitter.java&r1=450187&p2=jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionOutputBuffer.java&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NIOHttpDataTransmitter.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/SessionOutputBuffer.java Sun Oct  8 05:34:28 2006
@@ -30,100 +30,54 @@
 package org.apache.http.nio.impl;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
+import java.nio.channels.WritableByteChannel;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
 
 import org.apache.http.io.CharArrayBuffer;
-import org.apache.http.io.HttpDataTransmitter;
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
 import org.apache.http.protocol.HTTP;
 
-/**
- * Abstract data transmitter implementation based on <code>java.nio</code>.
- *
- * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
- *
- *
- * <!-- empty lines above to avoid 'svn diff' context problems -->
- * @version $Revision$
- * 
- * @since 4.0
- */
-public abstract class NIOHttpDataTransmitter implements HttpDataTransmitter {
+public class SessionOutputBuffer extends ExpandableBuffer {
 
     private static final byte[] CRLF = new byte[] {HTTP.CR, HTTP.LF};
 
-    private ByteBuffer buffer = null;
-
+    private CharBuffer charbuffer = null;
     private Charset charset = null;
     private CharsetEncoder charencoder = null;
-    private CharBuffer chbuffer = null;
-
-    protected void initBuffer(int buffersize, int linebuffersize) {
-        this.buffer = ByteBuffer.allocateDirect(buffersize);
+    
+    public SessionOutputBuffer(int buffersize, int linebuffersize) {
+        super(buffersize);
+        this.charbuffer = CharBuffer.allocate(linebuffersize);
         this.charset = Charset.forName("US-ASCII");
-        this.charencoder = createCharEncoder();
-        this.chbuffer = CharBuffer.allocate(linebuffersize);
+        this.charencoder = this.charset.newEncoder();
     }
-    
+
     public void reset(final HttpParams params) {
         this.charset = Charset.forName(HttpProtocolParams.getHttpElementCharset(params)); 
-        this.charencoder = createCharEncoder();
+        this.charencoder = this.charset.newEncoder();
     }
 
-    private void doFlushBuffer() throws IOException {
-        this.buffer.flip();
-        flushBuffer();
-        this.buffer.compact();
-    }
-    
-    protected ByteBuffer getBuffer() {
-        return this.buffer;
-    }
-    
-    protected abstract void flushBuffer() throws IOException;
-    
-    public  void flush() throws IOException {
-        this.buffer.flip();
-        while (this.buffer.hasRemaining()) {
-            flushBuffer();
+    public int flush(final WritableByteChannel channel) throws IOException {
+        if (channel == null) {
+            throw new IllegalArgumentException("Channel may not be null");
         }
-        this.buffer.clear();
-    }
-    
-    private CharsetEncoder createCharEncoder() {
-        CharsetEncoder charencoder = this.charset.newEncoder();
-        charencoder.onMalformedInput(CodingErrorAction.REPLACE); 
-        charencoder.onUnmappableCharacter(CodingErrorAction.REPLACE); 
-        return charencoder; 
+        setOutputMode();
+        int noWritten = channel.write(this.buffer);
+        return noWritten;
     }
-    
+
     public void write(final byte[] b, int off, int len) throws IOException {
         if (b == null) {
             return;
         }
-        int remaining = len;
-        while (remaining > 0) {
-            if (this.buffer.hasRemaining()) {
-                int chunk = len;
-                if (chunk > remaining) {
-                    chunk = remaining;
-                }
-                if (chunk > this.buffer.remaining()) {
-                    chunk = this.buffer.remaining();
-                }
-                this.buffer.put(b, off, chunk);
-                off += chunk;
-                remaining -= chunk; 
-            } else {
-                doFlushBuffer();
-            }
-        }
+        setInputMode();
+        int requiredCapacity = this.buffer.position() + len;
+        ensureCapacity(requiredCapacity);
+        this.buffer.put(b, off, len);
     }
 
     public void write(final byte[] b) throws IOException {
@@ -138,42 +92,43 @@
     }
 
     public void write(int b) throws IOException {
-        if (!this.buffer.hasRemaining()) {
-            doFlushBuffer();
-        }
+        setInputMode();
+        int requiredCapacity = this.buffer.position() + 1;
+        ensureCapacity(requiredCapacity);
         this.buffer.put((byte)b);
     }
 
-    public void writeLine(final CharArrayBuffer buffer) throws IOException {
-        if (buffer == null) {
+    public void writeLine(final CharArrayBuffer linebuffer) throws IOException {
+        if (linebuffer == null) {
             return;
         }
         // Do not bother if the buffer is empty
-        if (buffer.length() > 0 ) {
+        if (linebuffer.length() > 0 ) {
+            setInputMode();
         	this.charencoder.reset();
             // transfer the string in small chunks
-            int remaining = buffer.length();
+            int remaining = linebuffer.length();
             int offset = 0;
             while (remaining > 0) {
-                int l = this.chbuffer.remaining();
+                int l = this.charbuffer.remaining();
                 boolean eol = false;
                 if (remaining < l) {
                     l = remaining;
                     // terminate the encoding process
                     eol = true;
                 }
-                this.chbuffer.put(buffer.buffer(), offset, l);
-                this.chbuffer.flip();
+                this.charbuffer.put(linebuffer.buffer(), offset, l);
+                this.charbuffer.flip();
                 
                 boolean retry = true;
                 while (retry) {
-                    CoderResult result = this.charencoder.encode(this.chbuffer, this.buffer, eol);
+                    CoderResult result = this.charencoder.encode(this.charbuffer, this.buffer, eol);
                     if (result.isOverflow()) {
-                        doFlushBuffer();
+                        expand();
                     }
                     retry = !result.isUnderflow();
                 }
-                this.chbuffer.compact();
+                this.charbuffer.compact();
                 offset += l;
                 remaining -= l;
             }
@@ -182,7 +137,7 @@
             while (retry) {
                 CoderResult result = this.charencoder.flush(this.buffer);
                 if (result.isOverflow()) {
-                    doFlushBuffer();
+                    expand();
                 }
                 retry = !result.isUnderflow();
             }
@@ -190,17 +145,4 @@
         writeCRLF();
     }
 
-    public void writeLine(final String s) throws IOException {
-        if (s == null) {
-            return;
-        }
-        if (s.length() > 0) {
-            CharArrayBuffer tmp = new CharArrayBuffer(s.length());
-            tmp.append(s);
-            writeLine(tmp);
-        } else {
-            write(CRLF);
-        }
-    }
-    
 }

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestAllImpl.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestAllImpl.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestAllImpl.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestAllImpl.java Sun Oct  8 05:34:28 2006
@@ -38,6 +38,7 @@
 
     public static Test suite() {
         TestSuite suite = new TestSuite();
+        suite.addTest(TestSessionBuffers.suite());
         suite.addTest(TestNIOHttpTransmitterAndReceiver.suite());
         return suite;
     }

Added: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestSessionBuffers.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestSessionBuffers.java?view=auto&rev=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestSessionBuffers.java (added)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestSessionBuffers.java Sun Oct  8 05:34:28 2006
@@ -0,0 +1,176 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ * ====================================================================
+ *
+ *  Copyright 1999-2006 The Apache Software Foundation
+ *
+ *  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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.nio.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.http.io.CharArrayBuffer;
+
+/**
+ * Simple tests for {@link SessionInputBuffer}.
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ * 
+ * @version $Id$
+ */
+public class TestSessionBuffers extends TestCase {
+
+    // ------------------------------------------------------------ Constructor
+    public TestSessionBuffers(String testName) {
+        super(testName);
+    }
+
+    // ------------------------------------------------------------------- Main
+    public static void main(String args[]) {
+        String[] testCaseName = { TestSessionBuffers.class.getName() };
+        junit.textui.TestRunner.main(testCaseName);
+    }
+
+    // ------------------------------------------------------- TestCase Methods
+
+    public static Test suite() {
+        return new TestSuite(TestSessionBuffers.class);
+    }
+
+    private static WritableByteChannel newChannel(final ByteArrayOutputStream outstream) {
+        return Channels.newChannel(outstream);
+    }
+    
+    private static ReadableByteChannel newChannel(final String s, final String charset) 
+            throws UnsupportedEncodingException {
+        return Channels.newChannel(new ByteArrayInputStream(s.getBytes(charset)));
+    }
+    
+    private static ReadableByteChannel newChannel(final String s) 
+            throws UnsupportedEncodingException {
+        return newChannel(s, "US-ASCII");
+    }
+
+    public void testReadLine() throws Exception {
+        
+        SessionInputBuffer inbuf = new SessionInputBuffer(16, 16);
+        
+        ReadableByteChannel channel = newChannel("One\r\nTwo\r\nThree");
+        
+        inbuf.fill(channel);
+        
+        CharArrayBuffer line = new CharArrayBuffer(64);
+        
+        line.clear();
+        assertTrue(inbuf.readLine(line, false));
+        assertEquals("One", line.toString());
+        
+        line.clear();
+        assertTrue(inbuf.readLine(line, false));
+        assertEquals("Two", line.toString());
+
+        line.clear();
+        assertFalse(inbuf.readLine(line, false));
+
+        channel = newChannel("\r\nFour");
+        inbuf.fill(channel);
+        
+        line.clear();
+        assertTrue(inbuf.readLine(line, false));
+        assertEquals("Three", line.toString());
+
+        inbuf.fill(channel);
+        
+        line.clear();
+        assertTrue(inbuf.readLine(line, true));
+        assertEquals("Four", line.toString());
+
+        line.clear();
+        assertFalse(inbuf.readLine(line, true));
+    }
+    
+    public void testWriteLine() throws Exception {
+        
+        SessionOutputBuffer outbuf = new SessionOutputBuffer(16, 16);
+        SessionInputBuffer inbuf = new SessionInputBuffer(16, 16);
+        
+        ReadableByteChannel inChannel = newChannel("One\r\nTwo\r\nThree");
+        
+        inbuf.fill(inChannel);
+        
+        CharArrayBuffer line = new CharArrayBuffer(64);
+        
+        line.clear();
+        assertTrue(inbuf.readLine(line, false));
+        assertEquals("One", line.toString());
+        
+        outbuf.writeLine(line);
+        
+        line.clear();
+        assertTrue(inbuf.readLine(line, false));
+        assertEquals("Two", line.toString());
+
+        outbuf.writeLine(line);
+        
+        line.clear();
+        assertFalse(inbuf.readLine(line, false));
+
+        inChannel = newChannel("\r\nFour");
+        inbuf.fill(inChannel);
+
+        line.clear();
+        assertTrue(inbuf.readLine(line, false));
+        assertEquals("Three", line.toString());
+
+        outbuf.writeLine(line);
+        
+        inbuf.fill(inChannel);
+        
+        line.clear();
+        assertTrue(inbuf.readLine(line, true));
+        assertEquals("Four", line.toString());
+
+        outbuf.writeLine(line);
+        
+        line.clear();
+        assertFalse(inbuf.readLine(line, true));
+
+        ByteArrayOutputStream outstream = new ByteArrayOutputStream(); 
+        WritableByteChannel outChannel = newChannel(outstream);
+        outbuf.flush(outChannel);
+        
+        String s = new String(outstream.toByteArray(), "US-ASCII");
+        assertEquals("One\r\nTwo\r\nThree\r\nFour\r\n", s);
+    }
+    
+}
\ No newline at end of file

Propchange: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestSessionBuffers.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/impl/TestSessionBuffers.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataReceiverMockup.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataReceiverMockup.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataReceiverMockup.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataReceiverMockup.java Sun Oct  8 05:34:28 2006
@@ -7,6 +7,7 @@
 import java.nio.channels.ReadableByteChannel;
 
 import org.apache.http.nio.impl.NIOHttpDataReceiver;
+import org.apache.http.nio.impl.SessionInputBuffer;
 
 /**
  * {@link HttpDataInputStream} mockup implementation.
@@ -23,12 +24,11 @@
             final ReadableByteChannel channel, 
             int buffersize, 
             int linebuffersize) {
-        super();
+        super(new SessionInputBuffer(buffersize, linebuffersize));
         if (channel == null) {
             throw new IllegalArgumentException("Channel may not be null");
         }
         this.channel = channel;
-        initBuffer(buffersize, linebuffersize);
     }
 
     public NIOHttpDataReceiverMockup(final byte[] bytes) {
@@ -39,9 +39,8 @@
             final byte[] bytes, 
             int buffersize, 
             int linebuffersize) {
-        super();
+        super(new SessionInputBuffer(buffersize, linebuffersize));
         this.channel = Channels.newChannel(new ByteArrayInputStream(bytes));
-        initBuffer(buffersize, linebuffersize);
     }
 
     public NIOHttpDataReceiverMockup(final String s, final String charset, int buffersize) 
@@ -55,8 +54,8 @@
     
     }
     
-    protected int fillBuffer() throws IOException {
-        return this.channel.read(getBuffer());
+    protected int waitForData() throws IOException {
+        return getBuffer().fill(this.channel);
     }
   
     public boolean isDataAvailable(int timeout) throws IOException {

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataTransmitterMockup.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataTransmitterMockup.java?view=diff&rev=454135&r1=454134&r2=454135
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataTransmitterMockup.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/mockup/NIOHttpDataTransmitterMockup.java Sun Oct  8 05:34:28 2006
@@ -6,6 +6,7 @@
 import java.nio.channels.WritableByteChannel;
 
 import org.apache.http.nio.impl.NIOHttpDataTransmitter;
+import org.apache.http.nio.impl.SessionOutputBuffer;
 
 /**
  * {@link HttpDataTransmitter} mockup implementation.
@@ -24,30 +25,27 @@
             final WritableByteChannel channel, 
             int buffersize,
             int linebuffersize) {
-        super();
+        super(new SessionOutputBuffer(buffersize, linebuffersize));
         if (channel == null) {
             throw new IllegalArgumentException("Channel may not be null");
         }
         this.channel = channel;
-        initBuffer(buffersize, linebuffersize);
     }
 
     public NIOHttpDataTransmitterMockup(
             int buffersize,
             int linebuffersize) {
-        super();
+        super(new SessionOutputBuffer(buffersize, linebuffersize));
         this.channel = Channels.newChannel(this.buffer);
-        initBuffer(buffersize, linebuffersize);
     }
 
     public NIOHttpDataTransmitterMockup() {
-        super();
+        super(new SessionOutputBuffer(BUFFER_SIZE, BUFFER_SIZE));
         this.channel = Channels.newChannel(this.buffer);
-        initBuffer(BUFFER_SIZE, BUFFER_SIZE);
     }
 
     protected void flushBuffer() throws IOException {
-        this.channel.write(getBuffer());
+        getBuffer().flush(this.channel);
     }
     
     public byte[] getData() {



Mime
View raw message