392237 Implemented HttpOutput.sendContent for large content

This commit is contained in:
Greg Wilkins 2012-10-19 10:16:30 +11:00
parent 11fb3fa91e
commit f420f5016d
12 changed files with 155 additions and 34 deletions

View File

@ -41,7 +41,7 @@ public class LikeJettyXml
{
public static void main(String[] args) throws Exception
{
String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution");
String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution");
System.setProperty("jetty.home",jetty_home);
// Setup Threadpool

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.http;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import org.eclipse.jetty.util.resource.Resource;
@ -38,6 +39,7 @@ public interface HttpContent
Resource getResource();
long getContentLength();
InputStream getInputStream() throws IOException;
ReadableByteChannel getReadableByteChannel() throws IOException;
void release();
/* ------------------------------------------------------------ */
@ -130,6 +132,13 @@ public interface HttpContent
{
return _resource.getInputStream();
}
/* ------------------------------------------------------------ */
@Override
public ReadableByteChannel getReadableByteChannel() throws IOException
{
return _resource.getReadableByteChannel();
}
/* ------------------------------------------------------------ */
@Override

View File

@ -120,6 +120,11 @@ public class ChannelEndPoint extends AbstractEndPoint implements SocketBased
{
LOG.debug(e);
}
finally
{
_ishut=true;
_oshut=true;
}
}
@Override
@ -179,7 +184,7 @@ public class ChannelEndPoint extends AbstractEndPoint implements SocketBased
}
LOG.debug("flushed {} {}", flushed, this);
}
catch (ClosedChannelException | EOFException | SocketException e)
catch (IOException e)
{
throw new EofException(e);
}

View File

@ -330,20 +330,16 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
if (!committed)
LOG.warn("Could not send response error 500: "+x);
}
else if (isCommitted())
{
if (!(x instanceof EofException))
LOG.warn("Could not send response error 500: "+x);
}
else
{
// TODO: this error handling here must be atomic as above.
// TODO: response.sendError() should call back the HttpChannel in order to perform the atomic commit
if (!isCommitted())
{
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,x);
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,x.getClass());
_response.sendError(500, x.getMessage());
}
else
{
LOG.warn("Could not send response error 500: "+x);
}
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,x);
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,x.getClass());
_response.sendError(500, x.getMessage());
}
}
catch (IOException e)

View File

@ -22,6 +22,7 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletOutputStream;
@ -32,6 +33,8 @@ import org.eclipse.jetty.http.HttpContent;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
/**
@ -46,6 +49,7 @@ import org.eclipse.jetty.util.resource.Resource;
*/
public class HttpOutput extends ServletOutputStream
{
private static Logger LOG = Log.getLogger(HttpOutput.class);
private final HttpChannel<?> _channel;
private boolean _closed;
private long _written;
@ -80,14 +84,22 @@ public class HttpOutput extends ServletOutputStream
}
@Override
public void close() throws IOException
public void close()
{
if (!_closed)
{
if (BufferUtil.hasContent(_aggregate))
_channel.write(_aggregate, !_channel.getResponse().isIncluding());
else
_channel.write(BufferUtil.EMPTY_BUFFER, !_channel.getResponse().isIncluding());
try
{
if (BufferUtil.hasContent(_aggregate))
_channel.write(_aggregate, !_channel.getResponse().isIncluding());
else
_channel.write(BufferUtil.EMPTY_BUFFER, !_channel.getResponse().isIncluding());
}
catch(IOException e)
{
_channel.getEndPoint().shutdownOutput();
LOG.ignore(e);
}
}
_closed = true;
if (_aggregate != null)
@ -228,6 +240,8 @@ public class HttpOutput extends ServletOutputStream
content = httpContent.getDirectBuffer();
if (content == null)
content = httpContent.getIndirectBuffer();
if (content == null)
content = httpContent.getReadableByteChannel();
if (content == null)
content = httpContent.getInputStream();
}
@ -243,12 +257,56 @@ public class HttpOutput extends ServletOutputStream
{
_channel.write((ByteBuffer)content, true); // TODO: we have written all content ?
}
else if (content instanceof ReadableByteChannel)
{
ReadableByteChannel channel = (ReadableByteChannel)content;
ByteBuffer buffer = _channel.getByteBufferPool().acquire(getBufferSize(), true);
try
{
while(channel.isOpen())
{
int pos = BufferUtil.flipToFill(buffer);
int len=channel.read(buffer);
if (len<0)
break;
BufferUtil.flipToFlush(buffer,pos);
_channel.write(buffer,false);
}
}
finally
{
close();
_channel.getByteBufferPool().release(buffer);
}
}
else if (content instanceof InputStream)
{
throw new IllegalArgumentException("not implemented!");
InputStream in = (InputStream)content;
ByteBuffer buffer = _channel.getByteBufferPool().acquire(getBufferSize(), false);
byte[] array = buffer.array();
int offset=buffer.arrayOffset();
int size=array.length-offset;
try
{
while(true)
{
int len=in.read(array,offset,size);
if (len<0)
break;
buffer.position(0);
buffer.limit(len);
_channel.write(buffer,false);
}
_channel.write(BufferUtil.EMPTY_BUFFER,true);
}
finally
{
close();
_channel.getByteBufferPool().release(buffer);
}
}
else
throw new IllegalArgumentException("unknown content type?");
throw new IllegalArgumentException("unknown content type "+content.getClass());
}
public int getBufferSize()

View File

@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
@ -526,6 +527,14 @@ public class ResourceCache
return _resource.getInputStream();
}
/* ------------------------------------------------------------ */
@Override
public ReadableByteChannel getReadableByteChannel() throws IOException
{
return _resource.getReadableByteChannel();
}
/* ------------------------------------------------------------ */
@Override

View File

@ -272,18 +272,6 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
}
}
/* ------------------------------------------------------------ */
protected Map<String,Object> getAttributeMap ()
{
return _attributes;
}
/* ------------------------------------------------------------ */
protected void addAttributes(Map<String,Object> map)
{
_attributes.putAll(map);
}
/* ------------------------------------------------------------ */
protected boolean access(long time)
{
@ -474,6 +462,12 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
}
}
/* ------------------------------------------------------------ */
protected void addAttributes(Map<String,Object> map)
{
_attributes.putAll(map);
}
/* ------------------------------------------------------------- */
public void setIdChanged(boolean changed)
{

View File

@ -29,6 +29,10 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.OpenOption;
import java.nio.file.StandardOpenOption;
import java.security.Permission;
import org.eclipse.jetty.util.IO;
@ -281,7 +285,14 @@ public class FileResource extends URLResource
{
return new FileInputStream(_file);
}
/* ------------------------------------------------------------ */
@Override
public ReadableByteChannel getReadableByteChannel() throws IOException
{
return FileChannel.open(_file.toPath(),StandardOpenOption.READ);
}
/* --------------------------------------------------------- */
/**
* Returns an output stream to the resource

View File

@ -27,6 +27,7 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.ReadableByteChannel;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Date;
@ -408,6 +409,13 @@ public abstract class Resource implements ResourceFactory
*/
public abstract InputStream getInputStream()
throws java.io.IOException;
/* ------------------------------------------------------------ */
/**
* Returns an readable bytechannel to the resource or null if one is not available.
*/
public abstract ReadableByteChannel getReadableByteChannel()
throws java.io.IOException;
/* ------------------------------------------------------------ */
/**

View File

@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@ -328,6 +329,22 @@ public class ResourceCollection extends Resource
}
return null;
}
/* ------------------------------------------------------------ */
@Override
public ReadableByteChannel getReadableByteChannel() throws IOException
{
if(_resources==null)
throw new IllegalStateException("*resources* not set.");
for(Resource r : _resources)
{
ReadableByteChannel channel = r.getReadableByteChannel();
if(channel!=null)
return channel;
}
return null;
}
/* ------------------------------------------------------------ */
@Override

View File

@ -25,6 +25,7 @@ import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.ReadableByteChannel;
import java.security.Permission;
import org.eclipse.jetty.util.URIUtil;
@ -224,6 +225,12 @@ public class URLResource extends Resource
}
}
/* ------------------------------------------------------------ */
@Override
public ReadableByteChannel getReadableByteChannel() throws IOException
{
return null;
}
/* ------------------------------------------------------------ */
/**

View File

@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.List;
@ -96,6 +97,12 @@ public class OrderingTest
return null;
}
@Override
public ReadableByteChannel getReadableByteChannel() throws IOException
{
return null;
}
/**
* @see org.eclipse.jetty.util.resource.Resource#getName()
*/