changeset 1010:2712133d5bce

simplify Buffer code
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 23 Oct 2016 22:23:50 -0600
parents c3a04bded909
children 4e7208df7741
files src/org/eclipse/jetty/io/AbstractBuffer.java src/org/eclipse/jetty/io/Buffer.java src/org/eclipse/jetty/io/ByteArrayBuffer.java src/org/eclipse/jetty/io/nio/DirectNIOBuffer.java src/org/eclipse/jetty/io/nio/IndirectNIOBuffer.java src/org/eclipse/jetty/io/nio/NIOBuffer.java src/org/eclipse/jetty/server/AbstractHttpConnection.java
diffstat 7 files changed, 902 insertions(+), 1126 deletions(-) [+]
line wrap: on
line diff
diff -r c3a04bded909 -r 2712133d5bce src/org/eclipse/jetty/io/AbstractBuffer.java
--- a/src/org/eclipse/jetty/io/AbstractBuffer.java	Sun Oct 23 21:28:56 2016 -0600
+++ b/src/org/eclipse/jetty/io/AbstractBuffer.java	Sun Oct 23 22:23:50 2016 -0600
@@ -92,15 +92,6 @@
 			return new ByteArrayBuffer(asArray(), 0, length(), access);
 	}
 	
-	/*
-	 * @see org.eclipse.io.Buffer#asNonVolatile()
-	 */
-	public Buffer asNonVolatileBuffer()
-	{
-		if (!isVolatile()) return this;
-		return duplicate(_access);
-	}
-
 	public Buffer asImmutableBuffer()
 	{
 		if (isImmutable()) return this;
@@ -116,18 +107,6 @@
 		return new View(this, markIndex(), getIndex(), putIndex(), READONLY);
 	}
 
-	public Buffer asMutableBuffer()
-	{
-		if (!isImmutable()) return this;
-		
-		Buffer b=this.buffer();
-		if (b.isReadOnly())
-		{
-			return duplicate(READWRITE);
-		}
-		return new View(b, markIndex(), getIndex(), putIndex(), _access);
-	}
-
 	public Buffer buffer()
 	{
 		return this;
@@ -669,32 +648,6 @@
 	}
 
 	/* ------------------------------------------------------------ */
-	public void writeTo(OutputStream out)
-		throws IOException
-	{
-		byte[] array = array();
-		
-		if (array!=null)
-		{
-			out.write(array,getIndex(),length());
-		}
-		else
-		{
-			int len = this.length();
-			byte[] buf=new byte[len>1024?1024:len];
-			int offset=_get;
-			while (len>0)
-			{
-				int l=peek(offset,buf,0,len>buf.length?buf.length:len);
-				out.write(buf,0,l);
-				offset+=l;
-				len-=l;
-			}
-		} 
-		clear();
-	}
-	
-	/* ------------------------------------------------------------ */
 	public int readFrom(InputStream in,int max) throws IOException
 	{
 		byte[] array = array();
diff -r c3a04bded909 -r 2712133d5bce src/org/eclipse/jetty/io/Buffer.java
--- a/src/org/eclipse/jetty/io/Buffer.java	Sun Oct 23 21:28:56 2016 -0600
+++ b/src/org/eclipse/jetty/io/Buffer.java	Sun Oct 23 22:23:50 2016 -0600
@@ -42,339 +42,321 @@
  */
 public interface Buffer extends Cloneable
 {
-    public final static int 
-      IMMUTABLE=0,  // neither indexes or contexts can be changed
-      READONLY=1,   // indexes may be changed, but not content
-      READWRITE=2;  // anything can be changed
-    public final boolean VOLATILE=true;     // The buffer may change outside of current scope.
-    public final boolean NON_VOLATILE=false;
+	public final static int 
+	  IMMUTABLE=0,  // neither indexes or contexts can be changed
+	  READONLY=1,   // indexes may be changed, but not content
+	  READWRITE=2;  // anything can be changed
+	public final boolean VOLATILE=true;     // The buffer may change outside of current scope.
+	public final boolean NON_VOLATILE=false;
 
-    /**
-     *  Get the underlying array, if one exists.
-     * @return a <code>byte[]</code> backing this buffer or null if none exists.
-     */
-    byte[] array();
-    
-    /**
-     * 
-     * @return a <code>byte[]</code> value of the bytes from the getIndex to the putIndex.
-     */
-    byte[] asArray();
-    
-    /** 
-     * Get the underlying buffer. If this buffer wraps a backing buffer.
-     * @return The root backing buffer or this if there is no backing buffer;
-     */
-    Buffer buffer();
-    
-    /**
-     * 
-     * @return a non volatile version of this <code>Buffer</code> value
-     */
-    Buffer asNonVolatileBuffer();
+	/**
+	 *  Get the underlying array, if one exists.
+	 * @return a <code>byte[]</code> backing this buffer or null if none exists.
+	 */
+	byte[] array();
+	
+	/**
+	 * 
+	 * @return a <code>byte[]</code> value of the bytes from the getIndex to the putIndex.
+	 */
+	byte[] asArray();
+	
+	/** 
+	 * Get the underlying buffer. If this buffer wraps a backing buffer.
+	 * @return The root backing buffer or this if there is no backing buffer;
+	 */
+	Buffer buffer();
+	
+	/**
+	 *
+	 * @return a readonly version of this <code>Buffer</code>.
+	 */
+	Buffer asReadOnlyBuffer();
 
-    /**
-     *
-     * @return a readonly version of this <code>Buffer</code>.
-     */
-    Buffer asReadOnlyBuffer();
-
-    /**
-     *
-     * @return an immutable version of this <code>Buffer</code>.
-     */
-    Buffer asImmutableBuffer();
+	/**
+	 *
+	 * @return an immutable version of this <code>Buffer</code>.
+	 */
+	Buffer asImmutableBuffer();
 
-    /**
-     *
-     * @return an immutable version of this <code>Buffer</code>.
-     */
-    Buffer asMutableBuffer();
-    
-    /**
-     * 
-     * The capacity of the buffer. This is the maximum putIndex that may be set.
-     * @return an <code>int</code> value
-     */
-    int capacity();
-    
-    /**
-     * the space remaining in the buffer.
-     * @return capacity - putIndex
-     */
-    int space();
-    
-    /**
-     * Clear the buffer. getIndex=0, putIndex=0.
-     */
-    void clear();
+	/**
+	 * 
+	 * The capacity of the buffer. This is the maximum putIndex that may be set.
+	 * @return an <code>int</code> value
+	 */
+	int capacity();
+	
+	/**
+	 * the space remaining in the buffer.
+	 * @return capacity - putIndex
+	 */
+	int space();
+	
+	/**
+	 * Clear the buffer. getIndex=0, putIndex=0.
+	 */
+	void clear();
 
-    /**
-     * Compact the buffer by discarding bytes before the postion (or mark if set).
-     * Bytes from the getIndex (or mark) to the putIndex are moved to the beginning of 
-     * the buffer and the values adjusted accordingly.
-     */
-    void compact();
-    
-    /**
-     * Get the byte at the current getIndex and increment it.
-     * @return The <code>byte</code> value from the current getIndex.
-     */
-    byte get();
-    
-    /**
-     * Get bytes from the current postion and put them into the passed byte array.
-     * The getIndex is incremented by the number of bytes copied into the array.
-     * @param b The byte array to fill.
-     * @param offset Offset in the array.
-     * @param length The max number of bytes to read.
-     * @return The number of bytes actually read.
-     */
-    int get(byte[] b, int offset, int length);
+	/**
+	 * Compact the buffer by discarding bytes before the postion (or mark if set).
+	 * Bytes from the getIndex (or mark) to the putIndex are moved to the beginning of 
+	 * the buffer and the values adjusted accordingly.
+	 */
+	void compact();
+	
+	/**
+	 * Get the byte at the current getIndex and increment it.
+	 * @return The <code>byte</code> value from the current getIndex.
+	 */
+	byte get();
+	
+	/**
+	 * Get bytes from the current postion and put them into the passed byte array.
+	 * The getIndex is incremented by the number of bytes copied into the array.
+	 * @param b The byte array to fill.
+	 * @param offset Offset in the array.
+	 * @param length The max number of bytes to read.
+	 * @return The number of bytes actually read.
+	 */
+	int get(byte[] b, int offset, int length);
 
-    /**
-     * 
-     * @param length an <code>int</code> value
-     * @return a <code>Buffer</code> value
-     */
-    Buffer get(int length);
+	/**
+	 * 
+	 * @param length an <code>int</code> value
+	 * @return a <code>Buffer</code> value
+	 */
+	Buffer get(int length);
 
-    /**
-     * The index within the buffer that will next be read or written.
-     * @return an <code>int</code> value >=0 <= putIndex()
-     */
-    int getIndex();
-    
-    /**
-     * @return true of putIndex > getIndex
-     */
-    boolean hasContent();
-    
-    /**
-     * 
-     * @return a <code>boolean</code> value true if case sensitive comparison on this buffer
-     */
-    boolean equalsIgnoreCase(Buffer buffer);
+	/**
+	 * The index within the buffer that will next be read or written.
+	 * @return an <code>int</code> value >=0 <= putIndex()
+	 */
+	int getIndex();
+	
+	/**
+	 * @return true of putIndex > getIndex
+	 */
+	boolean hasContent();
+	
+	/**
+	 * 
+	 * @return a <code>boolean</code> value true if case sensitive comparison on this buffer
+	 */
+	boolean equalsIgnoreCase(Buffer buffer);
 
 
-    /**
-     * 
-     * @return a <code>boolean</code> value true if the buffer is immutable and that neither
-     * the buffer contents nor the indexes may be changed.
-     */
-    boolean isImmutable();
-    
-    /**
-     * 
-     * @return a <code>boolean</code> value true if the buffer is readonly. The buffer indexes may
-     * be modified, but the buffer contents may not. For example a View onto an immutable Buffer will be
-     * read only.
-     */
-    boolean isReadOnly();
-    
-    /**
-     * 
-     * @return a <code>boolean</code> value true if the buffer contents may change 
-     * via alternate paths than this buffer.  If the contents of this buffer are to be used outside of the
-     * current context, then a copy must be made.
-     */
-    boolean isVolatile();
+	/**
+	 * 
+	 * @return a <code>boolean</code> value true if the buffer is immutable and that neither
+	 * the buffer contents nor the indexes may be changed.
+	 */
+	boolean isImmutable();
+	
+	/**
+	 * 
+	 * @return a <code>boolean</code> value true if the buffer is readonly. The buffer indexes may
+	 * be modified, but the buffer contents may not. For example a View onto an immutable Buffer will be
+	 * read only.
+	 */
+	boolean isReadOnly();
+	
+	/**
+	 * 
+	 * @return a <code>boolean</code> value true if the buffer contents may change 
+	 * via alternate paths than this buffer.  If the contents of this buffer are to be used outside of the
+	 * current context, then a copy must be made.
+	 */
+	boolean isVolatile();
 
-    /**
-     * The number of bytes from the getIndex to the putIndex
-     * @return an <code>int</code> == putIndex()-getIndex()
-     */
-    int length();
-    
-    /**
-     * Set the mark to the current getIndex.
-     */
-    void mark();
-    
-    /**
-     * Set the mark relative to the current getIndex
-     * @param offset an <code>int</code> value to add to the current getIndex to obtain the mark value.
-     */
-    void mark(int offset);
+	/**
+	 * The number of bytes from the getIndex to the putIndex
+	 * @return an <code>int</code> == putIndex()-getIndex()
+	 */
+	int length();
+	
+	/**
+	 * Set the mark to the current getIndex.
+	 */
+	void mark();
+	
+	/**
+	 * Set the mark relative to the current getIndex
+	 * @param offset an <code>int</code> value to add to the current getIndex to obtain the mark value.
+	 */
+	void mark(int offset);
 
-    /**
-     * The current index of the mark.
-     * @return an <code>int</code> index in the buffer or -1 if the mark is not set.
-     */
-    int markIndex();
+	/**
+	 * The current index of the mark.
+	 * @return an <code>int</code> index in the buffer or -1 if the mark is not set.
+	 */
+	int markIndex();
 
-    /**
-     * Get the byte at the current getIndex without incrementing the getIndex.
-     * @return The <code>byte</code> value from the current getIndex.
-     */
-    byte peek();
+	/**
+	 * Get the byte at the current getIndex without incrementing the getIndex.
+	 * @return The <code>byte</code> value from the current getIndex.
+	 */
+	byte peek();
   
-    /**
-     * Get the byte at a specific index in the buffer.
-     * @param index an <code>int</code> value
-     * @return a <code>byte</code> value
-     */
-    byte peek(int index);
+	/**
+	 * Get the byte at a specific index in the buffer.
+	 * @param index an <code>int</code> value
+	 * @return a <code>byte</code> value
+	 */
+	byte peek(int index);
 
-    /**
-     * 
-     * @param index an <code>int</code> value
-     * @param length an <code>int</code> value
-     * @return The <code>Buffer</code> value from the requested getIndex.
-     */
-    Buffer peek(int index, int length);
+	/**
+	 * 
+	 * @param index an <code>int</code> value
+	 * @param length an <code>int</code> value
+	 * @return The <code>Buffer</code> value from the requested getIndex.
+	 */
+	Buffer peek(int index, int length);
 
-    /**
-     * 
-     * @param index an <code>int</code> value
-     * @param b The byte array to peek into
-     * @param offset The offset into the array to start peeking
-     * @param length an <code>int</code> value
-     * @return The number of bytes actually peeked
-     */
-    int peek(int index, byte[] b, int offset, int length);
-    
-    /**
-     * Put the contents of the buffer at the specific index.
-     * @param index an <code>int</code> value
-     * @param src a <code>Buffer</code>. If the source buffer is not modified
-    
-     * @return The number of bytes actually poked
-     */
-    int poke(int index, Buffer src);
-    
-    /**
-     * Put a specific byte to a specific getIndex.
-     * @param index an <code>int</code> value
-     * @param b a <code>byte</code> value
-     */
-    void poke(int index, byte b);
-    
-    /**
-     * Put a specific byte to a specific getIndex.
-     * @param index an <code>int</code> value
-     * @param b a <code>byte array</code> value
-     * @return The number of bytes actually poked
-     */
-    int poke(int index, byte b[], int offset, int length);
-    
-    /**
-     * Write the bytes from the source buffer to the current getIndex.
-     * @param src The source <code>Buffer</code> it is not modified.
-     * @return The number of bytes actually poked
-     */
-    int put(Buffer src);
+	/**
+	 * 
+	 * @param index an <code>int</code> value
+	 * @param b The byte array to peek into
+	 * @param offset The offset into the array to start peeking
+	 * @param length an <code>int</code> value
+	 * @return The number of bytes actually peeked
+	 */
+	int peek(int index, byte[] b, int offset, int length);
+	
+	/**
+	 * Put the contents of the buffer at the specific index.
+	 * @param index an <code>int</code> value
+	 * @param src a <code>Buffer</code>. If the source buffer is not modified
+	
+	 * @return The number of bytes actually poked
+	 */
+	int poke(int index, Buffer src);
+	
+	/**
+	 * Put a specific byte to a specific getIndex.
+	 * @param index an <code>int</code> value
+	 * @param b a <code>byte</code> value
+	 */
+	void poke(int index, byte b);
+	
+	/**
+	 * Put a specific byte to a specific getIndex.
+	 * @param index an <code>int</code> value
+	 * @param b a <code>byte array</code> value
+	 * @return The number of bytes actually poked
+	 */
+	int poke(int index, byte b[], int offset, int length);
+	
+	/**
+	 * Write the bytes from the source buffer to the current getIndex.
+	 * @param src The source <code>Buffer</code> it is not modified.
+	 * @return The number of bytes actually poked
+	 */
+	int put(Buffer src);
 
-    /**
-     * Put a byte to the current getIndex and increment the getIndex.
-     * @param b a <code>byte</code> value
-     */
-    void put(byte b);
-    
-    /**
-     * Put a byte to the current getIndex and increment the getIndex.
-     * @param b a <code>byte</code> value
-     * @return The number of bytes actually poked
-     */
-    int put(byte[] b,int offset, int length);
-
-    /**
-     * Put a byte to the current getIndex and increment the getIndex.
-     * @param b a <code>byte</code> value
-     * @return The number of bytes actually poked
-     */
-    int put(byte[] b);
+	/**
+	 * Put a byte to the current getIndex and increment the getIndex.
+	 * @param b a <code>byte</code> value
+	 */
+	void put(byte b);
+	
+	/**
+	 * Put a byte to the current getIndex and increment the getIndex.
+	 * @param b a <code>byte</code> value
+	 * @return The number of bytes actually poked
+	 */
+	int put(byte[] b,int offset, int length);
 
-    /**
-     * The index of the first element that should not be read.
-     * @return an <code>int</code> value >= getIndex() 
-     */
-    int putIndex();
-    
-    /**
-     * Reset the current getIndex to the mark 
-     */
-    void reset();
-    
-    /**
-     * Set the buffers start getIndex.
-     * @param newStart an <code>int</code> value
-     */
-    void setGetIndex(int newStart);
-    
-    /**
-     * Set a specific value for the mark.
-     * @param newMark an <code>int</code> value
-     */
-    void setMarkIndex(int newMark);
-    
-    /**
-     * 
-     * @param newLimit an <code>int</code> value
-     */
-    void setPutIndex(int newLimit);
-    
-    /**
-     * Skip _content. The getIndex is updated by min(remaining(), n)
-     * @param n The number of bytes to skip
-     * @return the number of bytes skipped.
-     */
-    int skip(int n);
+	/**
+	 * Put a byte to the current getIndex and increment the getIndex.
+	 * @param b a <code>byte</code> value
+	 * @return The number of bytes actually poked
+	 */
+	int put(byte[] b);
 
-    /**
-     * 
-     * @return a volitile <code>Buffer</code> from the postion to the putIndex.
-     */
-    Buffer slice();
-    
-    /**
-     * 
-     *
-     * @return a volitile <code>Buffer</code> value from the mark to the putIndex
-     */
-    Buffer sliceFromMark();
-    
-    /**
-     * 
-     *
-     * @param length an <code>int</code> value
-     * @return a valitile <code>Buffer</code> value from the mark of the length requested.
-     */
-    Buffer sliceFromMark(int length);
-    
-    /**
-     * 
-     * @return a <code>String</code> value describing the state and contents of the buffer.
-     */
-    String toDetailString();
+	/**
+	 * The index of the first element that should not be read.
+	 * @return an <code>int</code> value >= getIndex() 
+	 */
+	int putIndex();
+	
+	/**
+	 * Reset the current getIndex to the mark 
+	 */
+	void reset();
+	
+	/**
+	 * Set the buffers start getIndex.
+	 * @param newStart an <code>int</code> value
+	 */
+	void setGetIndex(int newStart);
+	
+	/**
+	 * Set a specific value for the mark.
+	 * @param newMark an <code>int</code> value
+	 */
+	void setMarkIndex(int newMark);
+	
+	/**
+	 * 
+	 * @param newLimit an <code>int</code> value
+	 */
+	void setPutIndex(int newLimit);
+	
+	/**
+	 * Skip _content. The getIndex is updated by min(remaining(), n)
+	 * @param n The number of bytes to skip
+	 * @return the number of bytes skipped.
+	 */
+	int skip(int n);
 
-    /* ------------------------------------------------------------ */
-    /** Write the buffer's contents to the output stream
-     * @param out
-     */
-    void writeTo(OutputStream out) throws IOException;
-
-    /* ------------------------------------------------------------ */
-    /** Read the buffer's contents from the input stream
-     * @param in input stream
-     * @param max maximum number of bytes that may be read
-     * @return actual number of bytes read or -1 for EOF
-     */
-    int readFrom(InputStream in, int max) throws IOException;
-    
+	/**
+	 * 
+	 * @return a volitile <code>Buffer</code> from the postion to the putIndex.
+	 */
+	Buffer slice();
+	
+	/**
+	 * 
+	 *
+	 * @return a volitile <code>Buffer</code> value from the mark to the putIndex
+	 */
+	Buffer sliceFromMark();
+	
+	/**
+	 * 
+	 *
+	 * @param length an <code>int</code> value
+	 * @return a valitile <code>Buffer</code> value from the mark of the length requested.
+	 */
+	Buffer sliceFromMark(int length);
+	
+	/**
+	 * 
+	 * @return a <code>String</code> value describing the state and contents of the buffer.
+	 */
+	String toDetailString();
 
-    /* ------------------------------------------------------------ */
-    String toString(String charset);
-    
-    /* ------------------------------------------------------------ */
-    String toString(Charset charset);
+	/* ------------------------------------------------------------ */
+	/** Read the buffer's contents from the input stream
+	 * @param in input stream
+	 * @param max maximum number of bytes that may be read
+	 * @return actual number of bytes read or -1 for EOF
+	 */
+	int readFrom(InputStream in, int max) throws IOException;
+	
 
-    /*
-     * Buffers implementing this interface should be compared with case insensitive equals
-     *
-     */
-    public interface CaseInsensitve
-    {}
+	/* ------------------------------------------------------------ */
+	String toString(String charset);
+	
+	/* ------------------------------------------------------------ */
+	String toString(Charset charset);
 
-    
+	/*
+	 * Buffers implementing this interface should be compared with case insensitive equals
+	 *
+	 */
+	public interface CaseInsensitve
+	{}
+
+	
 }
diff -r c3a04bded909 -r 2712133d5bce src/org/eclipse/jetty/io/ByteArrayBuffer.java
--- a/src/org/eclipse/jetty/io/ByteArrayBuffer.java	Sun Oct 23 21:28:56 2016 -0600
+++ b/src/org/eclipse/jetty/io/ByteArrayBuffer.java	Sun Oct 23 22:23:50 2016 -0600
@@ -31,409 +31,385 @@
  */
 public class ByteArrayBuffer extends AbstractBuffer
 {
-    // Set a maximum size to a write for the writeTo method, to ensure that very large content is not
-    // written as a single write (which may fall foul to write timeouts if consumed slowly).
-    final static int MAX_WRITE=Integer.getInteger("org.eclipse.jetty.io.ByteArrayBuffer.MAX_WRITE",128*1024);
-    final protected byte[] _bytes;
+	// Set a maximum size to a write for the writeTo method, to ensure that very large content is not
+	// written as a single write (which may fall foul to write timeouts if consumed slowly).
+	final static int MAX_WRITE=Integer.getInteger("org.eclipse.jetty.io.ByteArrayBuffer.MAX_WRITE",128*1024);
+	final protected byte[] _bytes;
 
-    protected ByteArrayBuffer(int size, int access, boolean isVolatile)
-    {
-        this(new byte[size],0,0,access, isVolatile);
-    }
-    
-    public ByteArrayBuffer(byte[] bytes)
-    {
-        this(bytes, 0, bytes.length, READWRITE);
-    }
+	protected ByteArrayBuffer(int size, int access, boolean isVolatile)
+	{
+		this(new byte[size],0,0,access, isVolatile);
+	}
+	
+	public ByteArrayBuffer(byte[] bytes)
+	{
+		this(bytes, 0, bytes.length, READWRITE);
+	}
 
-    public ByteArrayBuffer(byte[] bytes, int index, int length)
-    {
-        this(bytes, index, length, READWRITE);
-    }
+	public ByteArrayBuffer(byte[] bytes, int index, int length)
+	{
+		this(bytes, index, length, READWRITE);
+	}
 
-    public ByteArrayBuffer(byte[] bytes, int index, int length, int access)
-    {
-        super(READWRITE, NON_VOLATILE);
-        _bytes = bytes;
-        setPutIndex(index + length);
-        setGetIndex(index);
-        _access = access;
-    }
+	public ByteArrayBuffer(byte[] bytes, int index, int length, int access)
+	{
+		super(READWRITE, NON_VOLATILE);
+		_bytes = bytes;
+		setPutIndex(index + length);
+		setGetIndex(index);
+		_access = access;
+	}
 
-    public ByteArrayBuffer(byte[] bytes, int index, int length, int access, boolean isVolatile)
-    {
-        super(READWRITE, isVolatile);
-        _bytes = bytes;
-        setPutIndex(index + length);
-        setGetIndex(index);
-        _access = access;
-    }
+	public ByteArrayBuffer(byte[] bytes, int index, int length, int access, boolean isVolatile)
+	{
+		super(READWRITE, isVolatile);
+		_bytes = bytes;
+		setPutIndex(index + length);
+		setGetIndex(index);
+		_access = access;
+	}
 
-    public ByteArrayBuffer(int size)
-    {
-        this(new byte[size], 0, 0, READWRITE);
-        setPutIndex(0);
-    }
+	public ByteArrayBuffer(int size)
+	{
+		this(new byte[size], 0, 0, READWRITE);
+		setPutIndex(0);
+	}
 
-    public ByteArrayBuffer(String value)
-    {
-        super(READWRITE,NON_VOLATILE);
-        _bytes = StringUtil.getBytes(value);
-        setGetIndex(0);
-        setPutIndex(_bytes.length);
-        _access=IMMUTABLE;
-        _string = value;
-    }
-    
-    public ByteArrayBuffer(String value,boolean immutable)
-    {
-        super(READWRITE,NON_VOLATILE);
-        _bytes = StringUtil.getBytes(value);
-        setGetIndex(0);
-        setPutIndex(_bytes.length);
-        if (immutable)
-        {
-            _access=IMMUTABLE;
-            _string = value;
-        }
-    }
+	public ByteArrayBuffer(String value)
+	{
+		super(READWRITE,NON_VOLATILE);
+		_bytes = StringUtil.getBytes(value);
+		setGetIndex(0);
+		setPutIndex(_bytes.length);
+		_access=IMMUTABLE;
+		_string = value;
+	}
+	
+	public ByteArrayBuffer(String value,boolean immutable)
+	{
+		super(READWRITE,NON_VOLATILE);
+		_bytes = StringUtil.getBytes(value);
+		setGetIndex(0);
+		setPutIndex(_bytes.length);
+		if (immutable)
+		{
+			_access=IMMUTABLE;
+			_string = value;
+		}
+	}
 
-    public ByteArrayBuffer(String value,String encoding) throws UnsupportedEncodingException
-    {
-        super(READWRITE,NON_VOLATILE);
-        _bytes = value.getBytes(encoding);
-        setGetIndex(0);
-        setPutIndex(_bytes.length);
-        _access=IMMUTABLE;
-        _string = value;
-    }
+	public ByteArrayBuffer(String value,String encoding) throws UnsupportedEncodingException
+	{
+		super(READWRITE,NON_VOLATILE);
+		_bytes = value.getBytes(encoding);
+		setGetIndex(0);
+		setPutIndex(_bytes.length);
+		_access=IMMUTABLE;
+		_string = value;
+	}
 
-    public byte[] array()
-    {
-        return _bytes;
-    }
+	public byte[] array()
+	{
+		return _bytes;
+	}
 
-    public int capacity()
-    {
-        return _bytes.length;
-    }
-    
-    @Override
-    public void compact()
-    {
-        if (isReadOnly()) 
-            throw new IllegalStateException(__READONLY);
-        int s = markIndex() >= 0 ? markIndex() : getIndex();
-        if (s > 0)
-        {
-            int length = putIndex() - s;
-            if (length > 0)
-            {
-                System.arraycopy(_bytes, s,_bytes, 0, length);
-            }
-            if (markIndex() > 0) setMarkIndex(markIndex() - s);
-            setGetIndex(getIndex() - s);
-            setPutIndex(putIndex() - s);
-        }
-    }
+	public int capacity()
+	{
+		return _bytes.length;
+	}
+	
+	@Override
+	public void compact()
+	{
+		if (isReadOnly()) 
+			throw new IllegalStateException(__READONLY);
+		int s = markIndex() >= 0 ? markIndex() : getIndex();
+		if (s > 0)
+		{
+			int length = putIndex() - s;
+			if (length > 0)
+			{
+				System.arraycopy(_bytes, s,_bytes, 0, length);
+			}
+			if (markIndex() > 0) setMarkIndex(markIndex() - s);
+			setGetIndex(getIndex() - s);
+			setPutIndex(putIndex() - s);
+		}
+	}
 
 
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (obj==this)
-            return true;
+	@Override
+	public boolean equals(Object obj)
+	{
+		if (obj==this)
+			return true;
 
-        if (obj == null || !(obj instanceof Buffer)) 
-            return false;
-        
-        if (obj instanceof Buffer.CaseInsensitve)
-            return equalsIgnoreCase((Buffer)obj);
-        
+		if (obj == null || !(obj instanceof Buffer)) 
+			return false;
+		
+		if (obj instanceof Buffer.CaseInsensitve)
+			return equalsIgnoreCase((Buffer)obj);
+		
 
-        Buffer b = (Buffer) obj;
-        
-        // reject different lengths
-        if (b.length() != length()) 
-            return false;
+		Buffer b = (Buffer) obj;
+		
+		// reject different lengths
+		if (b.length() != length()) 
+			return false;
 
-        // reject AbstractBuffer with different hash value
-        if (_hash != 0 && obj instanceof AbstractBuffer)
-        {
-            AbstractBuffer ab = (AbstractBuffer) obj;
-            if (ab._hash != 0 && _hash != ab._hash) 
-                return false;
-        }
+		// reject AbstractBuffer with different hash value
+		if (_hash != 0 && obj instanceof AbstractBuffer)
+		{
+			AbstractBuffer ab = (AbstractBuffer) obj;
+			if (ab._hash != 0 && _hash != ab._hash) 
+				return false;
+		}
 
-        // Nothing for it but to do the hard grind.
-        int get=getIndex();
-        int bi=b.putIndex();
-        for (int i = putIndex(); i-->get;)
-        {
-            byte b1 = _bytes[i];
-            byte b2 = b.peek(--bi);
-            if (b1 != b2) return false;
-        }
-        return true;
-    }
+		// Nothing for it but to do the hard grind.
+		int get=getIndex();
+		int bi=b.putIndex();
+		for (int i = putIndex(); i-->get;)
+		{
+			byte b1 = _bytes[i];
+			byte b2 = b.peek(--bi);
+			if (b1 != b2) return false;
+		}
+		return true;
+	}
 
 
-    @Override
-    public boolean equalsIgnoreCase(Buffer b)
-    {
-        if (b==this)
-            return true;
-        
-        // reject different lengths
-        if (b==null || b.length() != length()) 
-            return false;
+	@Override
+	public boolean equalsIgnoreCase(Buffer b)
+	{
+		if (b==this)
+			return true;
+		
+		// reject different lengths
+		if (b==null || b.length() != length()) 
+			return false;
 
-        // reject AbstractBuffer with different hash value
-        if (_hash != 0 && b instanceof AbstractBuffer)
-        {
-            AbstractBuffer ab = (AbstractBuffer) b;
-            if (ab._hash != 0 && _hash != ab._hash) return false;
-        }
+		// reject AbstractBuffer with different hash value
+		if (_hash != 0 && b instanceof AbstractBuffer)
+		{
+			AbstractBuffer ab = (AbstractBuffer) b;
+			if (ab._hash != 0 && _hash != ab._hash) return false;
+		}
 
-        // Nothing for it but to do the hard grind.
-        int get=getIndex();
-        int bi=b.putIndex();
-        byte[] barray=b.array();
-        if (barray==null)
-        {
-            for (int i = putIndex(); i-->get;)
-            {
-                byte b1 = _bytes[i];
-                byte b2 = b.peek(--bi);
-                if (b1 != b2)
-                {
-                    if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
-                    if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
-                    if (b1 != b2) return false;
-                }
-            }
-        }
-        else
-        {
-            for (int i = putIndex(); i-->get;)
-            {
-                byte b1 = _bytes[i];
-                byte b2 = barray[--bi];
-                if (b1 != b2)
-                {
-                    if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
-                    if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
-                    if (b1 != b2) return false;
-                }
-            }
-        }
-        return true;
-    }
+		// Nothing for it but to do the hard grind.
+		int get=getIndex();
+		int bi=b.putIndex();
+		byte[] barray=b.array();
+		if (barray==null)
+		{
+			for (int i = putIndex(); i-->get;)
+			{
+				byte b1 = _bytes[i];
+				byte b2 = b.peek(--bi);
+				if (b1 != b2)
+				{
+					if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
+					if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
+					if (b1 != b2) return false;
+				}
+			}
+		}
+		else
+		{
+			for (int i = putIndex(); i-->get;)
+			{
+				byte b1 = _bytes[i];
+				byte b2 = barray[--bi];
+				if (b1 != b2)
+				{
+					if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
+					if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
+					if (b1 != b2) return false;
+				}
+			}
+		}
+		return true;
+	}
 
-    @Override
-    public byte get()
-    {
-        return _bytes[_get++];
-    }
+	@Override
+	public byte get()
+	{
+		return _bytes[_get++];
+	}
 
-    @Override
-    public int hashCode()
-    {
-        if (_hash == 0 || _hashGet!=_get || _hashPut!=_put) 
-        {
-            int get=getIndex();
-            for (int i = putIndex(); i-- >get;)
-            {
-                byte b = _bytes[i];
-                if ('a' <= b && b <= 'z') 
-                    b = (byte) (b - 'a' + 'A');
-                _hash = 31 * _hash + b;
-            }
-            if (_hash == 0) 
-                _hash = -1;
-            _hashGet=_get;
-            _hashPut=_put;
-        }
-        return _hash;
-    }
-    
-    
-    public byte peek(int index)
-    {
-        return _bytes[index];
-    }
-    
-    public int peek(int index, byte[] b, int offset, int length)
-    {
-        int l = length;
-        if (index + l > capacity())
-        {
-            l = capacity() - index;
-            if (l==0)
-                return -1;
-        }
-        
-        if (l < 0) 
-            return -1;
-        
-        System.arraycopy(_bytes, index, b, offset, l);
-        return l;
-    }
+	@Override
+	public int hashCode()
+	{
+		if (_hash == 0 || _hashGet!=_get || _hashPut!=_put) 
+		{
+			int get=getIndex();
+			for (int i = putIndex(); i-- >get;)
+			{
+				byte b = _bytes[i];
+				if ('a' <= b && b <= 'z') 
+					b = (byte) (b - 'a' + 'A');
+				_hash = 31 * _hash + b;
+			}
+			if (_hash == 0) 
+				_hash = -1;
+			_hashGet=_get;
+			_hashPut=_put;
+		}
+		return _hash;
+	}
+	
+	
+	public byte peek(int index)
+	{
+		return _bytes[index];
+	}
+	
+	public int peek(int index, byte[] b, int offset, int length)
+	{
+		int l = length;
+		if (index + l > capacity())
+		{
+			l = capacity() - index;
+			if (l==0)
+				return -1;
+		}
+		
+		if (l < 0) 
+			return -1;
+		
+		System.arraycopy(_bytes, index, b, offset, l);
+		return l;
+	}
 
-    public void poke(int index, byte b)
-    {
-        /* 
-        if (isReadOnly()) 
-            throw new IllegalStateException(__READONLY);
-        
-        if (index < 0) 
-            throw new IllegalArgumentException("index<0: " + index + "<0");
-        if (index > capacity())
-                throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
-        */
-        _bytes[index] = b;
-    }
-    
-    @Override
-    public int poke(int index, Buffer src)
-    {
-        _hash=0;
-        
-        /* 
-        if (isReadOnly()) 
-            throw new IllegalStateException(__READONLY);
-        if (index < 0) 
-            throw new IllegalArgumentException("index<0: " + index + "<0");
-        */
-        
-        int length=src.length();
-        if (index + length > capacity())
-        {
-            length=capacity()-index;
-            /*
-            if (length<0)
-                throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
-            */
-        }
-        
-        byte[] src_array = src.array();
-        if (src_array != null)
-            System.arraycopy(src_array, src.getIndex(), _bytes, index, length);
-        else 
-        {
-            int s=src.getIndex();
-            for (int i=0;i<length;i++)
-                _bytes[index++]=src.peek(s++);
-        }
-        
-        return length;
-    }
-    
+	public void poke(int index, byte b)
+	{
+		/* 
+		if (isReadOnly()) 
+			throw new IllegalStateException(__READONLY);
+		
+		if (index < 0) 
+			throw new IllegalArgumentException("index<0: " + index + "<0");
+		if (index > capacity())
+				throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
+		*/
+		_bytes[index] = b;
+	}
+	
+	@Override
+	public int poke(int index, Buffer src)
+	{
+		_hash=0;
+		
+		/* 
+		if (isReadOnly()) 
+			throw new IllegalStateException(__READONLY);
+		if (index < 0) 
+			throw new IllegalArgumentException("index<0: " + index + "<0");
+		*/
+		
+		int length=src.length();
+		if (index + length > capacity())
+		{
+			length=capacity()-index;
+			/*
+			if (length<0)
+				throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
+			*/
+		}
+		
+		byte[] src_array = src.array();
+		if (src_array != null)
+			System.arraycopy(src_array, src.getIndex(), _bytes, index, length);
+		else 
+		{
+			int s=src.getIndex();
+			for (int i=0;i<length;i++)
+				_bytes[index++]=src.peek(s++);
+		}
+		
+		return length;
+	}
+	
 
-    @Override
-    public int poke(int index, byte[] b, int offset, int length)
-    {
-        _hash=0;
-        /*
-        if (isReadOnly()) 
-            throw new IllegalStateException(__READONLY);
-        if (index < 0) 
-            throw new IllegalArgumentException("index<0: " + index + "<0");
-        */
-        
-        if (index + length > capacity())
-        {
-            length=capacity()-index;
-            /* if (length<0)
-                throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
-            */
-        }
-        
-        System.arraycopy(b, offset, _bytes, index, length);
-        
-        return length;
-    }
-    
-    /* ------------------------------------------------------------ */
-    @Override
-    public void writeTo(OutputStream out)
-        throws IOException
-    {
-        int len=length();
-        if (MAX_WRITE>0 && len>MAX_WRITE)
-        {
-            int off=getIndex();
-            while(len>0)
-            {
-                int c=len>MAX_WRITE?MAX_WRITE:len;
-                out.write(_bytes,off,c);
-                off+=c;
-                len-=c;
-            }
-        }
-        else
-            out.write(_bytes,getIndex(),len);
-        if (!isImmutable())
-            clear();
-    }
-    
-    /* ------------------------------------------------------------ */
-    @Override
-    public int readFrom(InputStream in,int max) throws IOException
-    {
-        if (max<0||max>space())
-            max=space();
-        int p = putIndex();
-        
-        int len=0, total=0, available=max;
-        while (total<max) 
-        {
-            len=in.read(_bytes,p,available);
-            if (len<0)
-                break;
-            else if (len>0)
-            {
-                p += len;
-                total += len;
-                available -= len;
-                setPutIndex(p);
-            }
-            if (in.available()<=0)
-                break;
-        }
-        if (len<0 && total==0)
-            return -1;
-        return total;
-    }
+	@Override
+	public int poke(int index, byte[] b, int offset, int length)
+	{
+		_hash=0;
+		/*
+		if (isReadOnly()) 
+			throw new IllegalStateException(__READONLY);
+		if (index < 0) 
+			throw new IllegalArgumentException("index<0: " + index + "<0");
+		*/
+		
+		if (index + length > capacity())
+		{
+			length=capacity()-index;
+			/* if (length<0)
+				throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
+			*/
+		}
+		
+		System.arraycopy(b, offset, _bytes, index, length);
+		
+		return length;
+	}
+	
+	@Override
+	public int readFrom(InputStream in,int max) throws IOException
+	{
+		if (max<0||max>space())
+			max=space();
+		int p = putIndex();
+		
+		int len=0, total=0, available=max;
+		while (total<max) 
+		{
+			len=in.read(_bytes,p,available);
+			if (len<0)
+				break;
+			else if (len>0)
+			{
+				p += len;
+				total += len;
+				available -= len;
+				setPutIndex(p);
+			}
+			if (in.available()<=0)
+				break;
+		}
+		if (len<0 && total==0)
+			return -1;
+		return total;
+	}
 
-    /* ------------------------------------------------------------ */
-    @Override
-    public int space()
-    {
-        return _bytes.length - _put;
-    }
+	/* ------------------------------------------------------------ */
+	@Override
+	public int space()
+	{
+		return _bytes.length - _put;
+	}
 
-    
-    /* ------------------------------------------------------------ */
-    /* ------------------------------------------------------------ */
-    /* ------------------------------------------------------------ */
-    public static class CaseInsensitive extends ByteArrayBuffer implements Buffer.CaseInsensitve
-    {
-        public CaseInsensitive(String s)
-        {
-            super(s);
-        }
-        
-        public CaseInsensitive(byte[] b, int o, int l, int rw)
-        {
-            super(b,o,l,rw);
-        }
+	
+	/* ------------------------------------------------------------ */
+	/* ------------------------------------------------------------ */
+	/* ------------------------------------------------------------ */
+	public static class CaseInsensitive extends ByteArrayBuffer implements Buffer.CaseInsensitve
+	{
+		public CaseInsensitive(String s)
+		{
+			super(s);
+		}
+		
+		public CaseInsensitive(byte[] b, int o, int l, int rw)
+		{
+			super(b,o,l,rw);
+		}
 
-        @Override
-        public boolean equals(Object obj)
-        {
-            return obj instanceof Buffer && equalsIgnoreCase((Buffer)obj);
-        }
-        
-    }
+		@Override
+		public boolean equals(Object obj)
+		{
+			return obj instanceof Buffer && equalsIgnoreCase((Buffer)obj);
+		}
+		
+	}
 }
diff -r c3a04bded909 -r 2712133d5bce src/org/eclipse/jetty/io/nio/DirectNIOBuffer.java
--- a/src/org/eclipse/jetty/io/nio/DirectNIOBuffer.java	Sun Oct 23 21:28:56 2016 -0600
+++ b/src/org/eclipse/jetty/io/nio/DirectNIOBuffer.java	Sun Oct 23 22:23:50 2016 -0600
@@ -35,320 +35,229 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/* ------------------------------------------------------------------------------- */
-/** 
- * 
- * 
- */
-public class DirectNIOBuffer extends AbstractBuffer implements NIOBuffer
+
+public final class DirectNIOBuffer extends AbstractBuffer implements NIOBuffer
 { 	
-    private static final Logger LOG = LoggerFactory.getLogger(DirectNIOBuffer.class);
+	private static final Logger LOG = LoggerFactory.getLogger(DirectNIOBuffer.class);
+
+	protected final ByteBuffer _buf;
+	private ReadableByteChannel _in;
+	private InputStream _inStream;
 
-    protected final ByteBuffer _buf;
-    private ReadableByteChannel _in;
-    private InputStream _inStream;
-    private WritableByteChannel _out;
-    private OutputStream _outStream;
+	public DirectNIOBuffer(int size)
+	{
+		super(READWRITE,NON_VOLATILE);
+		_buf = ByteBuffer.allocateDirect(size);
+		_buf.position(0);
+		_buf.limit(_buf.capacity());
+	}
+
 
-    public DirectNIOBuffer(int size)
-    {
-        super(READWRITE,NON_VOLATILE);
-        _buf = ByteBuffer.allocateDirect(size);
-        _buf.position(0);
-        _buf.limit(_buf.capacity());
-    }
-    
-    public DirectNIOBuffer(ByteBuffer buffer,boolean immutable)
-    {
-        super(immutable?IMMUTABLE:READWRITE,NON_VOLATILE);
-        if (!buffer.isDirect())
-            throw new IllegalArgumentException();
-        _buf = buffer;
-        setGetIndex(buffer.position());
-        setPutIndex(buffer.limit());
-    }
+	@Override
+	public boolean isDirect()
+	{
+		return true;
+	}
 
-    /**
-     * @param file
-     */
-    public DirectNIOBuffer(File file) throws IOException
-    {
-        super(READONLY,NON_VOLATILE);
-        FileInputStream fis = null;
-        FileChannel fc = null;
-        try
-        {
-            fis = new FileInputStream(file);
-            fc = fis.getChannel();
-            _buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
-            setGetIndex(0);
-            setPutIndex((int)file.length());
-            _access=IMMUTABLE;
-        }
-        finally
-        {
-            if (fc != null) try {fc.close();} catch (IOException e){LOG.trace("",e);}
-            IO.close(fis);
-        }
-    }
+	@Override
+	public byte[] array()
+	{
+		return null;
+	}
+
+	@Override
+	public int capacity()
+	{
+		return _buf.capacity();
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean isDirect()
-    {
-        return true;
-    }
-
-    /* ------------------------------------------------------------ */
-    public byte[] array()
-    {
-        return null;
-    }
-
-    /* ------------------------------------------------------------ */
-    public int capacity()
-    {
-        return _buf.capacity();
-    }
-
-    /* ------------------------------------------------------------ */
-    public byte peek(int position)
-    {
-        return _buf.get(position);
-    }
+	@Override
+	public byte peek(int position)
+	{
+		return _buf.get(position);
+	}
 
-    public int peek(int index, byte[] b, int offset, int length)
-    {
-        int l = length;
-        if (index+l > capacity())
-        {
-            l=capacity()-index;
-            if (l==0)
-                return -1;
-        }
-        
-        if (l < 0) 
-            return -1;
-        try
-        {
-            _buf.position(index);
-            _buf.get(b,offset,l);
-        }
-        finally
-        {
-            _buf.position(0);
-        }
-        
-        return l;
-    }
+	@Override
+	public int peek(int index, byte[] b, int offset, int length)
+	{
+		int l = length;
+		if (index+l > capacity())
+		{
+			l=capacity()-index;
+			if (l==0)
+				return -1;
+		}
+		
+		if (l < 0) 
+			return -1;
+		try
+		{
+			_buf.position(index);
+			_buf.get(b,offset,l);
+		}
+		finally
+		{
+			_buf.position(0);
+		}
+		
+		return l;
+	}
 
-    public void poke(int index, byte b)
-    {
-        if (isReadOnly()) throw new IllegalStateException(__READONLY);
-        if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0");
-        if (index > capacity())
-                throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
-        _buf.put(index,b);
-    }
+	@Override
+	public void poke(int index, byte b)
+	{
+		if (isReadOnly()) throw new IllegalStateException(__READONLY);
+		if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0");
+		if (index > capacity())
+				throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
+		_buf.put(index,b);
+	}
 
-    @Override
-    public int poke(int index, Buffer src)
-    {
-        if (isReadOnly()) throw new IllegalStateException(__READONLY);
+	@Override
+	public int poke(int index, Buffer src)
+	{
+		if (isReadOnly()) throw new IllegalStateException(__READONLY);
 
-        byte[] array=src.array();
-        if (array!=null)
-        {
-            return poke(index,array,src.getIndex(),src.length());
-        }
-        else
-        {
-            Buffer src_buf=src.buffer();
-            if (src_buf instanceof DirectNIOBuffer)
-            {
-                ByteBuffer src_bytebuf = ((DirectNIOBuffer)src_buf)._buf;
-                if (src_bytebuf==_buf)
-                    src_bytebuf=_buf.duplicate();
-                try
-                {   
-                    _buf.position(index);
-                    int space = _buf.remaining();
-                    
-                    int length=src.length();
-                    if (length>space)    
-                        length=space;
-                    
-                    src_bytebuf.position(src.getIndex());
-                    src_bytebuf.limit(src.getIndex()+length);
-                    
-                    _buf.put(src_bytebuf);
-                    return length;
-                }
-                finally
-                {
-                    _buf.position(0);
-                    src_bytebuf.limit(src_bytebuf.capacity());
-                    src_bytebuf.position(0);
-                }
-            }
-            else
-                return super.poke(index,src);
-        }
-    }
-    
-    @Override
-    public int poke(int index, byte[] b, int offset, int length)
-    {
-        if (isReadOnly()) throw new IllegalStateException(__READONLY);
+		byte[] array=src.array();
+		if (array!=null)
+		{
+			return poke(index,array,src.getIndex(),src.length());
+		}
+		else
+		{
+			Buffer src_buf=src.buffer();
+			if (src_buf instanceof DirectNIOBuffer)
+			{
+				ByteBuffer src_bytebuf = ((DirectNIOBuffer)src_buf)._buf;
+				if (src_bytebuf==_buf)
+					src_bytebuf=_buf.duplicate();
+				try
+				{   
+					_buf.position(index);
+					int space = _buf.remaining();
+					
+					int length=src.length();
+					if (length>space)    
+						length=space;
+					
+					src_bytebuf.position(src.getIndex());
+					src_bytebuf.limit(src.getIndex()+length);
+					
+					_buf.put(src_bytebuf);
+					return length;
+				}
+				finally
+				{
+					_buf.position(0);
+					src_bytebuf.limit(src_bytebuf.capacity());
+					src_bytebuf.position(0);
+				}
+			}
+			else
+				return super.poke(index,src);
+		}
+	}
+	
+	@Override
+	public int poke(int index, byte[] b, int offset, int length)
+	{
+		if (isReadOnly()) throw new IllegalStateException(__READONLY);
 
-        if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0");
-
-        if (index + length > capacity())
-        {
-            length=capacity()-index;
-            if (length<0)
-                throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
-        }
+		if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0");
 
-        try
-        {
-            _buf.position(index);
-            
-            int space=_buf.remaining();
-            
-            if (length>space)
-                length=space;
-            if (length>0)
-                _buf.put(b,offset,length);
-            return length;
-        }
-        finally
-        {
-            _buf.position(0);
-        }
-    }
-    
-    /* ------------------------------------------------------------ */
-    public ByteBuffer getByteBuffer()
-    {
-        return _buf;
-    }
-
-    /* ------------------------------------------------------------ */
-    @Override
-    public int readFrom(InputStream in, int max) throws IOException
-    {
-        if (_in==null || !_in.isOpen() || in!=_inStream)
-        {
-            _in=Channels.newChannel(in);
-            _inStream=in;
-        }
+		if (index + length > capacity())
+		{
+			length=capacity()-index;
+			if (length<0)
+				throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
+		}
 
-        if (max<0 || max>space())
-            max=space();
-        int p = putIndex();
-        
-        try
-        {
-            int len=0, total=0, available=max;
-            int loop=0;
-            while (total<max) 
-            {
-                _buf.position(p);
-                _buf.limit(p+available);
-                len=_in.read(_buf);
-                if (len<0)
-                {
-                    _in=null;
-                    _inStream=in;
-                    break;
-                }
-                else if (len>0)
-                {
-                    p += len;
-                    total += len;
-                    available -= len;
-                    setPutIndex(p);
-                    loop=0;
-                }
-                else if (loop++>1)
-                    break;
-                if (in.available()<=0)
-                    break;
-            }
-            if (len<0 && total==0)
-                return -1;
-            return total;
-            
-        }
-        catch(IOException e)
-        {
-            _in=null;
-            _inStream=in;
-            throw e;
-        }
-        finally
-        {
-            if (_in!=null && !_in.isOpen())
-            {
-                _in=null;
-                _inStream=in;
-            }
-            _buf.position(0);
-            _buf.limit(_buf.capacity());
-        }
-    }
+		try
+		{
+			_buf.position(index);
+			
+			int space=_buf.remaining();
+			
+			if (length>space)
+				length=space;
+			if (length>0)
+				_buf.put(b,offset,length);
+			return length;
+		}
+		finally
+		{
+			_buf.position(0);
+		}
+	}
+	
+	@Override
+	public ByteBuffer getByteBuffer()
+	{
+		return _buf;
+	}
+
+	@Override
+	public int readFrom(InputStream in, int max) throws IOException
+	{
+		if (_in==null || !_in.isOpen() || in!=_inStream)
+		{
+			_in = Channels.newChannel(in);
+			_inStream = in;
+		}
 
-    /* ------------------------------------------------------------ */
-    @Override
-    public void writeTo(OutputStream out) throws IOException
-    {
-        if (_out==null || !_out.isOpen() || out!=_outStream)
-        {
-            _out=Channels.newChannel(out);
-            _outStream=out;
-        }
+		if (max<0 || max>space())
+			max=space();
+		int p = putIndex();
+		
+		try
+		{
+			int len=0, total=0, available=max;
+			int loop=0;
+			while (total<max) 
+			{
+				_buf.position(p);
+				_buf.limit(p+available);
+				len = _in.read(_buf);
+				if (len<0)
+				{
+					_in = null;
+					_inStream = in;
+					break;
+				}
+				else if (len>0)
+				{
+					p += len;
+					total += len;
+					available -= len;
+					setPutIndex(p);
+					loop=0;
+				}
+				else if (loop++>1)
+					break;
+				if (in.available()<=0)
+					break;
+			}
+			if (len<0 && total==0)
+				return -1;
+			return total;
+			
+		}
+		catch(IOException e)
+		{
+			_in = null;
+			_inStream = in;
+			throw e;
+		}
+		finally
+		{
+			if (_in!=null && !_in.isOpen())
+			{
+				_in = null;
+				_inStream = in;
+			}
+			_buf.position(0);
+			_buf.limit(_buf.capacity());
+		}
+	}
 
-        synchronized (_buf)
-        {
-            try
-            {
-                int loop=0;
-                while(hasContent() && _out.isOpen())
-                {
-                    _buf.position(getIndex());
-                    _buf.limit(putIndex());
-                    int len=_out.write(_buf);
-                    if (len<0)
-                        break;
-                    else if (len>0)
-                    {
-                        skip(len);
-                        loop=0;
-                    }
-                    else if (loop++>1)
-                        break;
-                }
-
-            }
-            catch(IOException e)
-            {
-                _out=null;
-                _outStream=null;
-                throw e;
-            }
-            finally
-            {
-                if (_out!=null && !_out.isOpen())
-                {
-                    _out=null;
-                    _outStream=null;
-                }
-                _buf.position(0);
-                _buf.limit(_buf.capacity());
-            }
-        }
-    }
-
-    
-    
 }
diff -r c3a04bded909 -r 2712133d5bce src/org/eclipse/jetty/io/nio/IndirectNIOBuffer.java
--- a/src/org/eclipse/jetty/io/nio/IndirectNIOBuffer.java	Sun Oct 23 21:28:56 2016 -0600
+++ b/src/org/eclipse/jetty/io/nio/IndirectNIOBuffer.java	Sun Oct 23 22:23:50 2016 -0600
@@ -22,41 +22,28 @@
 
 import org.eclipse.jetty.io.ByteArrayBuffer;
 
-public class IndirectNIOBuffer extends ByteArrayBuffer implements NIOBuffer
+
+public final class IndirectNIOBuffer extends ByteArrayBuffer implements NIOBuffer
 {
-    protected final ByteBuffer _buf;
+	private final ByteBuffer _buf;
 
-    /* ------------------------------------------------------------ */
-    public IndirectNIOBuffer(int size)
-    {
-        super(size,READWRITE,NON_VOLATILE);
-        _buf = ByteBuffer.wrap(_bytes);
-        _buf.position(0);
-        _buf.limit(_buf.capacity());
-    }
+	public IndirectNIOBuffer(int size)
+	{
+		super(size,READWRITE,NON_VOLATILE);
+		_buf = ByteBuffer.wrap(_bytes);
+		_buf.position(0);
+		_buf.limit(_buf.capacity());
+	}
 
-    /* ------------------------------------------------------------ */
-    public IndirectNIOBuffer(ByteBuffer buffer,boolean immutable)
-    {
-        super(buffer.array(),0,0, immutable?IMMUTABLE:READWRITE,NON_VOLATILE);
-        if (buffer.isDirect())
-            throw new IllegalArgumentException();
-        _buf = buffer;
-        _get=buffer.position();
-        _put=buffer.limit();
-        buffer.position(0);
-        buffer.limit(buffer.capacity());
-    }
-    
-    /* ------------------------------------------------------------ */
-    public ByteBuffer getByteBuffer()
-    {
-        return _buf;
-    }
+	@Override
+	public ByteBuffer getByteBuffer()
+	{
+		return _buf;
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean isDirect()
-    {
-        return false;
-    }
+	@Override
+	public boolean isDirect()
+	{
+		return false;
+	}
 }
diff -r c3a04bded909 -r 2712133d5bce src/org/eclipse/jetty/io/nio/NIOBuffer.java
--- a/src/org/eclipse/jetty/io/nio/NIOBuffer.java	Sun Oct 23 21:28:56 2016 -0600
+++ b/src/org/eclipse/jetty/io/nio/NIOBuffer.java	Sun Oct 23 22:23:50 2016 -0600
@@ -22,16 +22,10 @@
 
 import org.eclipse.jetty.io.Buffer;
 
-/* ------------------------------------------------------------------------------- */
-/** 
- * 
- * 
- */
+
 public interface NIOBuffer extends Buffer
 {
-    /* ------------------------------------------------------------ */
-    public ByteBuffer getByteBuffer();
+	public ByteBuffer getByteBuffer();
 
-    /* ------------------------------------------------------------ */
-    public boolean isDirect();
+	public boolean isDirect();
 }
diff -r c3a04bded909 -r 2712133d5bce src/org/eclipse/jetty/server/AbstractHttpConnection.java
--- a/src/org/eclipse/jetty/server/AbstractHttpConnection.java	Sun Oct 23 21:28:56 2016 -0600
+++ b/src/org/eclipse/jetty/server/AbstractHttpConnection.java	Sun Oct 23 22:23:50 2016 -0600
@@ -817,62 +817,37 @@
 			writer.print(s);
 		}
 
-		public void sendContent(Object content) throws IOException
+		public final void sendContent(InputStream in) throws IOException
 		{
-			Resource resource=null;
-
 			if (_closed)
 				throw new IOException("Closed");
 
 			if (_generator.isWritten())
 				throw new IllegalStateException("!empty");
 
-			if (content instanceof Resource)
+			try
 			{
-				resource=(Resource)content;
-				_responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, resource.lastModified());
-				content=resource.getInputStream();
-			}
-
-			// Process content.
-			if (content instanceof Buffer)
-			{
-				_generator.addContent((Buffer) content, HttpGenerator.LAST);
-				commitResponse(HttpGenerator.LAST);
-			}
-			else if (content instanceof InputStream)
-			{
-				InputStream in = (InputStream)content;
+				int max = _generator.prepareUncheckedAddContent();
+				Buffer buffer = _generator.getUncheckedBuffer();
 
-				try
-				{
-					int max = _generator.prepareUncheckedAddContent();
-					Buffer buffer = _generator.getUncheckedBuffer();
-
-					int len=buffer.readFrom(in,max);
+				int len = buffer.readFrom(in,max);
 
-					while (len>=0)
-					{
-						_generator.completeUncheckedAddContent();
-						_out.flush();
-
-						max = _generator.prepareUncheckedAddContent();
-						buffer = _generator.getUncheckedBuffer();
-						len=buffer.readFrom(in,max);
-					}
+				while (len>=0)
+				{
 					_generator.completeUncheckedAddContent();
 					_out.flush();
+
+					max = _generator.prepareUncheckedAddContent();
+					buffer = _generator.getUncheckedBuffer();
+					len=buffer.readFrom(in,max);
 				}
-				finally
-				{
-					if (resource!=null)
-						resource.release();
-					else
-						in.close();
-				}
+				_generator.completeUncheckedAddContent();
+				_out.flush();
 			}
-			else
-				throw new IllegalArgumentException("unknown content type?");
+			finally
+			{
+				in.close();
+			}
 		}
 	}