Skip to content

Commit

Permalink
398467 Servlet 3.1 Non Blocking IO
Browse files Browse the repository at this point in the history
fixed ResourceHandler
  • Loading branch information
gregw committed May 16, 2013
1 parent 76b767f commit 0176856
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ public void start(final BundleContext context) throws Exception
@Override
public void contextInitialized(ServletContextEvent sce)
{
System.err.println("Context is initialized");
// System.err.println("Context is initialized");
}

@Override
public void contextDestroyed(ServletContextEvent sce)
{
System.err.println("CONTEXT IS DESTROYED!");
// System.err.println("CONTEXT IS DESTROYED!");
}

});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;

import javax.servlet.AsyncContext;
import javax.servlet.RequestDispatcher;
Expand All @@ -38,10 +40,12 @@
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.FileResource;
import org.eclipse.jetty.util.resource.Resource;


Expand All @@ -68,6 +72,8 @@ public class ResourceHandler extends HandlerWrapper
String _cacheControl;
boolean _directory;
boolean _etags;
int _minMemoryMappedContentLength=-1;
int _minAsyncContentLength=0;

/* ------------------------------------------------------------ */
public ResourceHandler()
Expand Down Expand Up @@ -105,6 +111,50 @@ public void setDirectoriesListed(boolean directory)
_directory = directory;
}

/* ------------------------------------------------------------ */
/** Get minimum memory mapped file content length.
* @return the minimum size in bytes of a file resource that will
* be served using a memory mapped buffer, or -1 (default) for no memory mapped
* buffers.
*/
public int getMinMemoryMappedContentLength()
{
return _minMemoryMappedContentLength;
}

/* ------------------------------------------------------------ */
/** Set minimum memory mapped file content length.
* @param minMemoryMappedFileSize the minimum size in bytes of a file resource that will
* be served using a memory mapped buffer, or -1 for no memory mapped
* buffers.
*/
public void setMinMemoryMappedContentLength(int minMemoryMappedFileSize)
{
_minMemoryMappedContentLength = minMemoryMappedFileSize;
}

/* ------------------------------------------------------------ */
/** Get the minimum content length for async handling.
* @return The minimum size in bytes of the content before asynchronous
* handling is used, or -1 for no async handling or 0 (default) for using
* {@link HttpServletResponse#getBufferSize()} as the minimum length.
*/
public int getMinAsyncContentLength()
{
return _minAsyncContentLength;
}

/* ------------------------------------------------------------ */
/** Set the minimum content length for async handling.
* @param minAsyncContentLength The minimum size in bytes of the content before asynchronous
* handling is used, or -1 for no async handling or 0 for using
* {@link HttpServletResponse#getBufferSize()} as the minimum length.
*/
public void setMinAsyncContentLength(int minAsyncContentLength)
{
_minAsyncContentLength = minAsyncContentLength;
}

/* ------------------------------------------------------------ */
/**
* @return True if ETag processing is done
Expand Down Expand Up @@ -361,9 +411,10 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
}

Resource resource = getResource(request);

// If resource is not found
if (resource==null || !resource.exists())
{
// inject the jetty-dir.css file if it matches
if (target.endsWith("/jetty-dir.css"))
{
resource = getStylesheet();
Expand All @@ -382,6 +433,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
// We are going to serve something
baseRequest.setHandled(true);

// handle directories
if (resource.isDirectory())
{
if (!request.getPathInfo().endsWith(URIUtil.SLASH))
Expand All @@ -401,7 +453,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
}
}

// set some headers
// Handle ETAGS
long last_modified=resource.lastModified();
String etag=null;
if (_etags)
Expand All @@ -417,7 +469,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
}
}


// Handle if modified since
if (last_modified>0)
{
long if_modified=request.getDateHeader(HttpHeader.IF_MODIFIED_SINCE.asString());
Expand All @@ -428,48 +480,88 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
}
}

// set the headers
String mime=_mimeTypes.getMimeByExtension(resource.toString());
if (mime==null)
mime=_mimeTypes.getMimeByExtension(request.getPathInfo());

// set the headers
doResponseHeaders(response,resource,mime!=null?mime.toString():null);
if (_etags)
baseRequest.getResponse().getHttpFields().put(HttpHeader.ETAG,etag);

if(skipContentBody)
return;


// Send the content
OutputStream out =null;
try {out = response.getOutputStream();}
catch(IllegalStateException e) {out = new WriterOutputStream(response.getWriter());}

if (last_modified>0)
response.setDateHeader(HttpHeader.LAST_MODIFIED.asString(),last_modified);

if (out instanceof HttpOutput && request.isAsyncSupported())
// Has the output been wrapped
if (!(out instanceof HttpOutput))
// Write content via wrapped output
resource.writeTo(out,0,resource.length());
else
{
final AsyncContext async = request.startAsync();
((HttpOutput)out).sendContent(resource.getReadableByteChannel(),new Callback()
// select async by size
int min_async_size=_minAsyncContentLength==0?response.getBufferSize():_minAsyncContentLength;

if (request.isAsyncSupported() &&
min_async_size>0 &&
resource.length()>=min_async_size)
{
@Override
public void succeeded()
final AsyncContext async = request.startAsync();
Callback callback = new Callback()
{
@Override
public void succeeded()
{
async.complete();
}

@Override
public void failed(Throwable x)
{
async.complete();
}
};

// Can we use a memory mapped file?
if (_minMemoryMappedContentLength>0 &&
resource.length()>_minMemoryMappedContentLength &&
resource instanceof FileResource)
{
async.complete();
ByteBuffer buffer = BufferUtil.toBuffer(resource.getFile());
((HttpOutput)out).sendContent(buffer,callback);
}

@Override
public void failed(Throwable x)
else // Do a blocking write of a channel (if available) or input stream
{
async.complete();
}
});
}
else
{
// Write content normally
resource.writeTo(out,0,resource.length());
ReadableByteChannel channel= resource.getReadableByteChannel();
if (channel!=null)
((HttpOutput)out).sendContent(channel,callback);
else
((HttpOutput)out).sendContent(resource.getInputStream(),callback);
}
}
else
{
// Can we use a memory mapped file?
if (_minMemoryMappedContentLength>0 &&
resource.length()>_minMemoryMappedContentLength &&
resource instanceof FileResource)
{
ByteBuffer buffer = BufferUtil.toBuffer(resource.getFile());
((HttpOutput)out).sendContent(buffer);
}
else // Do a blocking write of a channel (if available) or input stream
{
ReadableByteChannel channel= resource.getReadableByteChannel();
if (channel!=null)
((HttpOutput)out).sendContent(channel);
else
((HttpOutput)out).sendContent(resource.getInputStream());
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public static void setUp() throws Exception
_server.setConnectors(new Connector[] { _connector });

_resourceHandler = new ResourceHandler();
_resourceHandler.setMinAsyncContentLength(4096);
_resourceHandler.setMinMemoryMappedContentLength(8192);

_resourceHandler.setResourceBase(MavenTestingUtils.getTargetFile("test-classes/simple").getAbsolutePath());

_contextHandler = new ContextHandler("/resource");
Expand Down

0 comments on commit 0176856

Please sign in to comment.