view src/org/eclipse/jetty/io/nio/DirectNIOBuffer.java @ 1020:6be43ef1eb96

HttpHeaderValues uses StringCache
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 31 Oct 2016 22:24:41 -0600
parents 2712133d5bce
children 80cad9086593
line wrap: on
line source

//
//  ========================================================================
//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.io.nio;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

import org.eclipse.jetty.io.AbstractBuffer;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.util.IO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public final class DirectNIOBuffer extends AbstractBuffer implements NIOBuffer
{ 	
	private static final Logger LOG = LoggerFactory.getLogger(DirectNIOBuffer.class);

	protected final ByteBuffer _buf;
	private ReadableByteChannel _in;
	private InputStream _inStream;

	public DirectNIOBuffer(int size)
	{
		super(READWRITE,NON_VOLATILE);
		_buf = ByteBuffer.allocateDirect(size);
		_buf.position(0);
		_buf.limit(_buf.capacity());
	}


	@Override
	public boolean isDirect()
	{
		return true;
	}

	@Override
	public byte[] array()
	{
		return null;
	}

	@Override
	public int capacity()
	{
		return _buf.capacity();
	}

	@Override
	public byte peek(int position)
	{
		return _buf.get(position);
	}

	@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;
	}

	@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);

		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());
		}

		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;
		}

		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());
		}
	}

}