319334 improved resource cache

Made the cache use concurrent data structures
Removed the dual NIO/BIO caches
Use the cache for streaming data
made DefaultServlet check for shared cache
some javadoc cleanups

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2085 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-07-09 04:45:52 +00:00
parent 2605267f3f
commit 9f0a75da75
19 changed files with 455 additions and 629 deletions

View File

@ -1,4 +1,5 @@
jetty-7.2-SNAPSHOT
+ 319334 Concurrent, sharable ResourceCache
jetty-7.1.5.v20100705
+ Update ecj to 3.6 Helios release drop

View File

@ -157,7 +157,7 @@ public class ContentExchangeTest
getExchange.setMethod(HttpMethods.HEAD);
_client.send(getExchange);
int state = getExchange.waitForDone();
getExchange.waitForDone();
int responseStatus = getExchange.getResponseStatus();

View File

@ -534,7 +534,6 @@ public class HttpExchangeTest extends TestCase
}
catch(InterruptedException e)
{
System.err.println(e);
Log.debug(e);
}
catch(IOException e)

View File

@ -17,7 +17,6 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.client.ContentExchangeTest.TestHandler;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.security.Constraint;
@ -40,6 +39,7 @@ public class SecuredErrorStatusTest
private Realm _testRealm;
private Realm _dummyRealm;
@Override
public void testPutUnauthorized()
throws Exception
{
@ -60,6 +60,7 @@ public class SecuredErrorStatusTest
setRealm(_testRealm);
}
@Override
public void testGetUnauthorized()
throws Exception
{
@ -80,6 +81,7 @@ public class SecuredErrorStatusTest
setRealm(_testRealm);
}
@Override
protected void configureServer(Server server)
throws Exception
{

View File

@ -28,7 +28,8 @@ public interface HttpContent
{
Buffer getContentType();
Buffer getLastModified();
Buffer getBuffer();
Buffer getIndirectBuffer();
Buffer getDirectBuffer();
Resource getResource();
long getContentLength();
InputStream getInputStream() throws IOException;

View File

@ -46,6 +46,8 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.UncheckedPrintWriter;
import org.eclipse.jetty.server.nio.NIOConnector;
import org.eclipse.jetty.server.ssl.SslConnector;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
@ -1162,10 +1164,11 @@ public class HttpConnection implements Connection
if (super._generator.getContentWritten() > 0)
throw new IllegalStateException("!empty");
// Convert HTTP content to contentl
if (content instanceof HttpContent)
{
HttpContent c = (HttpContent) content;
Buffer contentType = c.getContentType();
HttpContent httpContent = (HttpContent) content;
Buffer contentType = httpContent.getContentType();
if (contentType != null && !_responseFields.containsKey(HttpHeaders.CONTENT_TYPE_BUFFER))
{
String enc = _response.getSetCharacterEncoding();
@ -1191,21 +1194,22 @@ public class HttpConnection implements Connection
}
}
}
if (c.getContentLength() > 0)
_responseFields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER, c.getContentLength());
Buffer lm = c.getLastModified();
long lml=c.getResource().lastModified();
if (httpContent.getContentLength() > 0)
_responseFields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER, httpContent.getContentLength());
Buffer lm = httpContent.getLastModified();
long lml=httpContent.getResource().lastModified();
if (lm != null)
_responseFields.put(HttpHeaders.LAST_MODIFIED_BUFFER, lm,lml);
else if (c.getResource()!=null)
else if (httpContent.getResource()!=null)
{
if (lml!=-1)
_responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, lml);
}
content = c.getBuffer();
boolean direct=_connector instanceof NIOConnector && ((NIOConnector)_connector).getUseDirectBuffers() && !(_connector instanceof SslConnector);
content = direct?httpContent.getDirectBuffer():httpContent.getIndirectBuffer();
if (content==null)
content=c.getInputStream();
content=httpContent.getInputStream();
}
else if (content instanceof Resource)
{
@ -1214,7 +1218,7 @@ public class HttpConnection implements Connection
content=resource.getInputStream();
}
// Process content.
if (content instanceof Buffer)
{
super._generator.addContent((Buffer) content, Generator.LAST);

View File

@ -13,11 +13,16 @@
package org.eclipse.jetty.server;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.http.HttpContent;
import org.eclipse.jetty.http.HttpFields;
@ -25,7 +30,9 @@ import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.View;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;
@ -34,38 +41,44 @@ import org.eclipse.jetty.util.resource.ResourceFactory;
/**
*
*/
public class ResourceCache extends AbstractLifeCycle
public class ResourceCache
{
protected final Map _cache;
private final ConcurrentMap<String,Content> _cache;
private final AtomicInteger _cachedSize;
private final AtomicInteger _cachedFiles;
private final boolean _useFileMappedBuffer;
private final ResourceFactory _factory;
private final MimeTypes _mimeTypes;
private int _maxCachedFileSize =1024*1024;
private int _maxCachedFiles=2048;
private int _maxCacheSize =16*1024*1024;
protected int _cachedSize;
protected int _cachedFiles;
protected Content _mostRecentlyUsed;
protected Content _leastRecentlyUsed;
private int _maxCacheSize =32*1024*1024;
/* ------------------------------------------------------------ */
/** Constructor.
* @param mimeTypes Mimetype to use for meta data
* @param fileMappedBuffers True if file mapped buffers can be used for DirectBuffers
*/
public ResourceCache(MimeTypes mimeTypes)
public ResourceCache(ResourceFactory factory, MimeTypes mimeTypes,boolean fileMappedBuffers)
{
_cache=new HashMap();
_factory = factory;
_cache=new ConcurrentHashMap<String,Content>();
_cachedSize=new AtomicInteger();
_cachedFiles=new AtomicInteger();
_useFileMappedBuffer=fileMappedBuffers;
_mimeTypes=mimeTypes;
}
/* ------------------------------------------------------------ */
public int getCachedSize()
{
return _cachedSize;
return _cachedSize.get();
}
/* ------------------------------------------------------------ */
public int getCachedFiles()
{
return _cachedFiles;
return _cachedFiles.get();
}
@ -79,7 +92,7 @@ public class ResourceCache extends AbstractLifeCycle
public void setMaxCachedFileSize(int maxCachedFileSize)
{
_maxCachedFileSize = maxCachedFileSize;
flushCache();
shrinkCache();
}
/* ------------------------------------------------------------ */
@ -92,7 +105,7 @@ public class ResourceCache extends AbstractLifeCycle
public void setMaxCacheSize(int maxCacheSize)
{
_maxCacheSize = maxCacheSize;
flushCache();
shrinkCache();
}
/* ------------------------------------------------------------ */
@ -111,6 +124,7 @@ public class ResourceCache extends AbstractLifeCycle
public void setMaxCachedFiles(int maxCachedFiles)
{
_maxCachedFiles = maxCachedFiles;
shrinkCache();
}
/* ------------------------------------------------------------ */
@ -118,18 +132,14 @@ public class ResourceCache extends AbstractLifeCycle
{
if (_cache!=null)
{
synchronized(this)
while (_cache.size()>0)
{
ArrayList<Content> values=new ArrayList<Content>(_cache.values());
for (Content content : values)
content.invalidate();
_cache.clear();
_cachedSize=0;
_cachedFiles=0;
_mostRecentlyUsed=null;
_leastRecentlyUsed=null;
for (String path : _cache.keySet())
{
Content content = _cache.remove(path);
if (content!=null)
content.invalidate();
}
}
}
}
@ -139,49 +149,26 @@ public class ResourceCache extends AbstractLifeCycle
* Get either a valid entry object or create a new one if possible.
*
* @param pathInContext The key into the cache
* @param factory If no matching entry is found, this {@link ResourceFactory} will be used to create the {@link Resource}
* for the new enry that is created.
* @return The entry matching <code>pathInContext</code>, or a new entry if no matching entry was found
* @throws IOException Problem loading the resource
*/
public Content lookup(String pathInContext, ResourceFactory factory)
public Content lookup(String pathInContext)
throws IOException
{
Content content=null;
// Look up cache operations
synchronized(_cache)
{
// Look for it in the cache
content = (Content)_cache.get(pathInContext);
content = _cache.get(pathInContext);
if (content!=null && content.isValid())
{
return content;
}
}
Resource resource=factory.getResource(pathInContext);
return load(pathInContext,resource);
if (content!=null && content.isValid())
return content;
Resource resource=_factory.getResource(pathInContext);
Content loaded = load(pathInContext,resource);
return loaded;
}
/* ------------------------------------------------------------ */
public Content lookup(String pathInContext, Resource resource)
throws IOException
{
Content content=null;
// Look up cache operations
synchronized(_cache)
{
// Look for it in the cache
content = (Content)_cache.get(pathInContext);
if (content!=null && content.isValid())
{
return content;
}
}
return load(pathInContext,resource);
}
/* ------------------------------------------------------------ */
private Content load(String pathInContext, Resource resource)
@ -191,115 +178,122 @@ public class ResourceCache extends AbstractLifeCycle
if (resource!=null && resource.exists() && !resource.isDirectory())
{
long len = resource.length();
// Will it fit in the cache?
if (len>0 && len<_maxCachedFileSize && len<_maxCacheSize)
{
int must_be_smaller_than=_maxCacheSize-(int)len;
// Create the Content (to increment the cache sizes before adding the content
content = new Content(pathInContext,resource);
synchronized(_cache)
{
// check the cache is not full of locked content before loading content
while(_leastRecentlyUsed!=null && (_cachedSize>must_be_smaller_than || (_maxCachedFiles>0 && _cachedFiles>=_maxCachedFiles)))
_leastRecentlyUsed.invalidate();
if(_cachedSize>must_be_smaller_than || (_maxCachedFiles>0 && _cachedFiles>=_maxCachedFiles))
return null;
}
// reduce the cache to an acceptable size.
shrinkCache();
content = new Content(resource);
fill(content);
synchronized(_cache)
// Add it to the cache.
Content added = _cache.putIfAbsent(pathInContext,content);
if (added!=null)
{
// check that somebody else did not fill this spot.
Content content2 =(Content)_cache.get(pathInContext);
if (content2!=null)
{
content.release();
return content2;
}
while(_leastRecentlyUsed!=null && (_cachedSize>must_be_smaller_than || (_maxCachedFiles>0 && _cachedFiles>=_maxCachedFiles)))
_leastRecentlyUsed.invalidate();
if(_cachedSize>must_be_smaller_than || (_maxCachedFiles>0 && _cachedFiles>=_maxCachedFiles))
return null; // this could waste an allocated File or DirectBuffer
content.cache(pathInContext);
return content;
content.invalidate();
content=added;
}
return content;
}
}
return null;
}
/* ------------------------------------------------------------ */
private void shrinkCache()
{
// While we need to shrink
while (_cache.size()>0 && (_cachedFiles.get()>_maxCachedFiles || _cachedSize.get()>_maxCacheSize))
{
// Scan the entire cache and generate an ordered list by last accessed time.
SortedSet<Content> sorted= new TreeSet<Content>(
new Comparator<Content>()
{
public int compare(Content c1, Content c2)
{
if (c1._lastAccessed<c2._lastAccessed)
return -1;
if (c1._lastAccessed>c2._lastAccessed)
return 1;
if (c1._length<c2._length)
return -1;
return c1._key.compareTo(c2._key);
}
});
for (Content content : _cache.values())
sorted.add(content);
// Invalidate least recently used first
for (Content content : sorted)
{
if (_cachedFiles.get()<=_maxCachedFiles && _cachedSize.get()<=_maxCacheSize)
break;
if (content==_cache.remove(content.getKey()))
content.invalidate();
}
}
}
/* ------------------------------------------------------------ */
/** Remember a Resource Miss!
* @param pathInContext
* @param resource
* @throws IOException
* @param pathInContext Path the cache resource at
* @param resource The resource to cache.
*/
public void miss(String pathInContext, Resource resource)
throws IOException
{
synchronized(_cache)
{
while(_maxCachedFiles>0 && _cachedFiles>=_maxCachedFiles && _leastRecentlyUsed!=null)
_leastRecentlyUsed.invalidate();
if (_maxCachedFiles>0 && _cachedFiles>=_maxCachedFiles)
return;
// check that somebody else did not fill this spot.
Miss miss = new Miss(resource);
Content content2 =(Content)_cache.get(pathInContext);
if (content2!=null)
{
miss.release();
return;
}
if (_maxCachedFiles>0 && _cachedFiles.get()>=_maxCachedFiles)
return;
miss.cache(pathInContext);
}
// check that somebody else did not fill this spot.
Miss miss = new Miss(pathInContext,resource);
if (_cache.putIfAbsent(pathInContext,miss)!=null)
miss.invalidate();
}
/* ------------------------------------------------------------ */
@Override
public synchronized void doStart()
throws Exception
{
_cache.clear();
_cachedSize=0;
_cachedFiles=0;
}
/* ------------------------------------------------------------ */
/** Stop the context.
*/
@Override
public void doStop()
throws InterruptedException
{
flushCache();
}
/* ------------------------------------------------------------ */
protected void fill(Content content)
throws IOException
protected Buffer getIndirectBuffer(Resource resource)
{
try
{
InputStream in = content.getResource().getInputStream();
int len=(int)content.getResource().length();
Buffer buffer = new ByteArrayBuffer(len);
buffer.readFrom(in,len);
in.close();
content.setBuffer(buffer);
int len=(int)resource.length();
Buffer buffer = new IndirectNIOBuffer(len);
InputStream is = resource.getInputStream();
buffer.readFrom(is,len);
is.close();
return buffer;
}
finally
catch(IOException e)
{
content.getResource().release();
Log.warn(e);
return null;
}
}
/* ------------------------------------------------------------ */
protected Buffer getDirectBuffer(Resource resource)
{
try
{
if (_useFileMappedBuffer && resource.getFile()!=null)
return new DirectNIOBuffer(resource.getFile());
int len=(int)resource.length();
Buffer buffer = new DirectNIOBuffer(len);
InputStream is = resource.getInputStream();
buffer.readFrom(is,len);
is.close();
return buffer;
}
catch(IOException e)
{
Log.warn(e);
return null;
}
}
@ -310,95 +304,34 @@ public class ResourceCache extends AbstractLifeCycle
public class Content implements HttpContent
{
final Resource _resource;
final int _length;
final String _key;
final long _lastModified;
boolean _locked;
String _key;
Content _prev;
Content _next;
final Buffer _lastModifiedBytes;
final Buffer _contentType;
Buffer _lastModifiedBytes;
Buffer _contentType;
Buffer _buffer;
volatile long _lastAccessed;
AtomicReference<Buffer> _indirectBuffer=new AtomicReference<Buffer>();
AtomicReference<Buffer> _directBuffer=new AtomicReference<Buffer>();
/* ------------------------------------------------------------ */
Content(Resource resource)
{
_resource=resource;
_next=this;
_prev=this;
_contentType=_mimeTypes.getMimeByExtension(_resource.toString());
_lastModified=resource.lastModified();
}
/* ------------------------------------------------------------ */
/**
* @return true if the content is locked in the cache
*/
public boolean isLocked()
{
return _locked;
}
/* ------------------------------------------------------------ */
/**
* @param locked true if the content is locked in the cache
*/
public void setLocked(boolean locked)
{
synchronized (_cache)
{
if (_locked && !locked)
{
_locked = locked;
_next=_mostRecentlyUsed;
_mostRecentlyUsed=this;
if (_next!=null)
_next._prev=this;
_prev=null;
if (_leastRecentlyUsed==null)
_leastRecentlyUsed=this;
}
else if (!_locked && locked)
{
if (_prev!=null)
_prev._next=_next;
if (_next!=null)
_next._prev=_prev;
_next=_prev=null;
}
else
_locked = locked;
}
}
/* ------------------------------------------------------------ */
void cache(String pathInContext)
Content(String pathInContext,Resource resource)
{
_key=pathInContext;
_resource=resource;
_contentType=_mimeTypes.getMimeByExtension(_resource.toString());
boolean exists=resource.exists();
_lastModified=exists?resource.lastModified():-1;
_lastModifiedBytes=_lastModified<0?null:new ByteArrayBuffer(HttpFields.formatDate(_lastModified));
if (!_locked)
{
_next=_mostRecentlyUsed;
_mostRecentlyUsed=this;
if (_next!=null)
_next._prev=this;
_prev=null;
if (_leastRecentlyUsed==null)
_leastRecentlyUsed=this;
}
_cache.put(_key,this);
if (_buffer!=null)
_cachedSize+=_buffer.length();
_cachedFiles++;
if (_lastModified!=-1)
_lastModifiedBytes=new ByteArrayBuffer(HttpFields.formatDate(_lastModified));
_length=exists?(int)resource.length():0;
_cachedSize.addAndGet(_length);
_cachedFiles.incrementAndGet();
_lastAccessed=System.currentTimeMillis();
}
/* ------------------------------------------------------------ */
public String getKey()
{
@ -422,59 +355,22 @@ public class ResourceCache extends AbstractLifeCycle
{
if (_lastModified==_resource.lastModified())
{
if (!_locked && _mostRecentlyUsed!=this)
{
Content tp = _prev;
Content tn = _next;
_next=_mostRecentlyUsed;
_mostRecentlyUsed=this;
if (_next!=null)
_next._prev=this;
_prev=null;
if (tp!=null)
tp._next=tn;
if (tn!=null)
tn._prev=tp;
if (_leastRecentlyUsed==this && tp!=null)
_leastRecentlyUsed=tp;
}
_lastAccessed=System.currentTimeMillis();
return true;
}
invalidate();
if (this==_cache.remove(_key))
invalidate();
return false;
}
/* ------------------------------------------------------------ */
public void invalidate()
protected void invalidate()
{
synchronized(this)
{
// Invalidate it
_cache.remove(_key);
_key=null;
if (_buffer!=null)
_cachedSize=_cachedSize-_buffer.length();
_cachedFiles--;
if (_mostRecentlyUsed==this)
_mostRecentlyUsed=_next;
else
_prev._next=_next;
if (_leastRecentlyUsed==this)
_leastRecentlyUsed=_prev;
else
_next._prev=_prev;
_prev=null;
_next=null;
_resource.release();
}
// Invalidate it
_cachedSize.addAndGet(-_length);
_cachedFiles.decrementAndGet();
_resource.release();
}
/* ------------------------------------------------------------ */
@ -489,46 +385,67 @@ public class ResourceCache extends AbstractLifeCycle
return _contentType;
}
/* ------------------------------------------------------------ */
public void setContentType(Buffer type)
{
_contentType=type;
}
/* ------------------------------------------------------------ */
public void release()
{
// don't release while cached. Release when invalidated.
}
/* ------------------------------------------------------------ */
public Buffer getBuffer()
public Buffer getIndirectBuffer()
{
if (_buffer==null)
Buffer buffer = _indirectBuffer.get();
if (buffer==null)
{
synchronized (_indirectBuffer)
{
if (_indirectBuffer.get()==null)
{
buffer=ResourceCache.this.getIndirectBuffer(_resource);
_indirectBuffer.set(buffer);
}
}
}
if (buffer==null)
return null;
return new View(_buffer);
return new View(buffer);
}
/* ------------------------------------------------------------ */
public Buffer getDirectBuffer()
{
Buffer buffer = _directBuffer.get();
if (buffer==null)
{
synchronized (_directBuffer)
{
if (_directBuffer.get()==null)
{
buffer=ResourceCache.this.getDirectBuffer(_resource);
_directBuffer.set(buffer);
}
}
}
if (buffer==null)
return null;
return new View(buffer);
}
/* ------------------------------------------------------------ */
public void setBuffer(Buffer buffer)
{
_buffer=buffer;
}
/* ------------------------------------------------------------ */
public long getContentLength()
{
if (_buffer==null)
{
if (_resource!=null)
return _resource.length();
return -1;
}
return _buffer.length();
return _length;
}
/* ------------------------------------------------------------ */
public InputStream getInputStream() throws IOException
{
Buffer indirect = getIndirectBuffer();
if (indirect!=null && indirect.array()!=null)
return new ByteArrayInputStream(indirect.array(),indirect.getIndex(),indirect.length());
return _resource.getInputStream();
}
@ -549,9 +466,9 @@ public class ResourceCache extends AbstractLifeCycle
*/
public class Miss extends Content
{
Miss(Resource resource)
Miss(String pathInContext,Resource resource)
{
super(resource);
super(pathInContext,resource);
}
/* ------------------------------------------------------------ */
@ -560,7 +477,8 @@ public class ResourceCache extends AbstractLifeCycle
{
if (_resource.exists())
{
invalidate();
if (this==_cache.remove(_key))
invalidate();
return false;
}
return true;

View File

@ -270,26 +270,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
return _vhosts;
}
/* ------------------------------------------------------------ */
/**
* @deprecated use {@link #setConnectorNames(String[])}
*/
@Deprecated
public void setHosts(String[] hosts)
{
setConnectorNames(hosts);
}
/* ------------------------------------------------------------ */
/** Get the hosts for the context.
* @deprecated
*/
@Deprecated
public String[] getHosts()
{
return getConnectorNames();
}
/* ------------------------------------------------------------ */
/**
* @return an array of connector names that this context

View File

@ -32,7 +32,7 @@ public class ResourceCacheTest
private Resource directory;
private File[] files=new File[10];
private String[] names=new String[files.length];
private ResourceCache cache = new ResourceCache(new MimeTypes());
private ResourceCache cache;
private ResourceFactory factory;
@Before
@ -40,7 +40,7 @@ public class ResourceCacheTest
{
for (int i=0;i<files.length;i++)
{
files[i]=File.createTempFile("RCT",".txt");
files[i]=File.createTempFile("R-"+i+"-",".txt");
files[i].deleteOnExit();
names[i]=files[i].getName();
FileOutputStream out = new FileOutputStream(files[i]);
@ -67,83 +67,111 @@ public class ResourceCacheTest
}
};
cache=new ResourceCache(factory,new MimeTypes(),false);
cache.setMaxCacheSize(95);
cache.setMaxCachedFileSize(85);
cache.setMaxCachedFiles(4);
cache.start();
}
@After
public void destroy() throws Exception
{
cache.stop();
cache.flushCache();
}
@Test
public void testResourceCache() throws Exception
{
assertTrue(cache.lookup("does not exist",factory)==null);
assertTrue(cache.lookup(names[9],factory)==null);
assertTrue(cache.lookup("does not exist")==null);
assertTrue(cache.lookup(names[9])==null);
Content content;
content=cache.lookup(names[8],factory);
content=cache.lookup(names[8]);
assertTrue(content!=null);
assertEquals(80,content.getContentLength());
assertEquals(80,cache.getCachedSize());
assertEquals(1,cache.getCachedFiles());
content=cache.lookup(names[1],factory);
Thread.sleep(2);
content=cache.lookup(names[1]);
assertEquals(90,cache.getCachedSize());
assertEquals(2,cache.getCachedFiles());
content=cache.lookup(names[2],factory);
Thread.sleep(2);
content=cache.lookup(names[2]);
assertEquals(30,cache.getCachedSize());
assertEquals(2,cache.getCachedFiles());
content=cache.lookup(names[3],factory);
Thread.sleep(2);
content=cache.lookup(names[3]);
assertEquals(60,cache.getCachedSize());
assertEquals(3,cache.getCachedFiles());
content=cache.lookup(names[4],factory);
Thread.sleep(2);
content=cache.lookup(names[4]);
assertEquals(90,cache.getCachedSize());
assertEquals(3,cache.getCachedFiles());
content=cache.lookup(names[5],factory);
Thread.sleep(2);
content=cache.lookup(names[5]);
assertEquals(90,cache.getCachedSize());
assertEquals(2,cache.getCachedFiles());
content=cache.lookup(names[6],factory);
Thread.sleep(2);
content=cache.lookup(names[6]);
assertEquals(60,cache.getCachedSize());
assertEquals(1,cache.getCachedFiles());
Thread.sleep(2);
FileOutputStream out = new FileOutputStream(files[6]);
out.write(' ');
out.close();
content=cache.lookup(names[7],factory);
content=cache.lookup(names[7]);
assertEquals(70,cache.getCachedSize());
assertEquals(1,cache.getCachedFiles());
content=cache.lookup(names[6],factory);
Thread.sleep(2);
content=cache.lookup(names[6]);
assertEquals(71,cache.getCachedSize());
assertEquals(2,cache.getCachedFiles());
content=cache.lookup(names[0],factory);
Thread.sleep(2);
content=cache.lookup(names[0]);
assertEquals(72,cache.getCachedSize());
assertEquals(3,cache.getCachedFiles());
content=cache.lookup(names[1],factory);
Thread.sleep(2);
content=cache.lookup(names[1]);
assertEquals(82,cache.getCachedSize());
assertEquals(4,cache.getCachedFiles());
content=cache.lookup(names[2],factory);
Thread.sleep(2);
content=cache.lookup(names[2]);
assertEquals(32,cache.getCachedSize());
assertEquals(4,cache.getCachedFiles());
content=cache.lookup(names[3],factory);
Thread.sleep(2);
content=cache.lookup(names[3]);
assertEquals(61,cache.getCachedSize());
assertEquals(4,cache.getCachedFiles());
Thread.sleep(2);
cache.flushCache();
assertEquals(0,cache.getCachedSize());
assertEquals(0,cache.getCachedFiles());

View File

@ -92,6 +92,9 @@ import org.eclipse.jetty.util.resource.ResourceFactory;
*
* resourceBase Set to replace the context resource base
*
* resourceCache If set, this is a context attribute name, which the servlet
* will use to look for a shared ResourceCache instance.
*
* relativeResourceBase
* Set with a pathname relative to the base of the
* servlet context root. Useful for only serving static content out
@ -103,9 +106,6 @@ import org.eclipse.jetty.util.resource.ResourceFactory;
* maxCacheSize The maximum total size of the cache or 0 for no cache.
* maxCachedFileSize The maximum size of a file to cache
* maxCachedFiles The maximum number of files to cache
* cacheType Set to "bio", "nio" or "both" to determine the type resource cache.
* A bio cached buffer may be used by nio but is not as efficient as an
* nio buffer. An nio cached buffer may not be used by bio.
*
* useFileMappedBuffer
* If set to true, it will use mapped file buffer to serve static content
@ -125,6 +125,7 @@ import org.eclipse.jetty.util.resource.ResourceFactory;
*/
public class DefaultServlet extends HttpServlet implements ResourceFactory
{
private static final long serialVersionUID = 4930458713846881193L;
private ServletContext _servletContext;
private ContextHandler _contextHandler;
@ -136,8 +137,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
private boolean _gzip=true;
private Resource _resourceBase;
private NIOResourceCache _nioCache;
private ResourceCache _bioCache;
private ResourceCache _cache;
private MimeTypes _mimeTypes;
private String[] _welcomes;
@ -209,50 +209,42 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
if (t!=null)
_cacheControl=new ByteArrayBuffer(t);
try
String resourceCache = getInitParameter("resourceCache");
int max_cache_size=getInitInt("maxCacheSize", -2);
int max_cached_file_size=getInitInt("maxCachedFileSize", -2);
int max_cached_files=getInitInt("maxCachedFiles", -2);
if (resourceCache!=null)
{
String cache_type =getInitParameter("cacheType");
int max_cache_size=getInitInt("maxCacheSize", -2);
int max_cached_file_size=getInitInt("maxCachedFileSize", -2);
int max_cached_files=getInitInt("maxCachedFiles", -2);
if (cache_type==null || "nio".equals(cache_type)|| "both".equals(cache_type))
{
if (max_cache_size==-2 || max_cache_size>0)
{
_nioCache=new NIOResourceCache(_mimeTypes);
_nioCache.setUseFileMappedBuffer(_useFileMappedBuffer);
if (max_cache_size>0)
_nioCache.setMaxCacheSize(max_cache_size);
if (max_cached_file_size>=-1)
_nioCache.setMaxCachedFileSize(max_cached_file_size);
if (max_cached_files>=-1)
_nioCache.setMaxCachedFiles(max_cached_files);
_nioCache.start();
}
}
if ("bio".equals(cache_type)|| "both".equals(cache_type))
{
if (max_cache_size==-2 || max_cache_size>0)
{
_bioCache=new ResourceCache(_mimeTypes);
if (max_cache_size>0)
_bioCache.setMaxCacheSize(max_cache_size);
if (max_cached_file_size>=-1)
_bioCache.setMaxCachedFileSize(max_cached_file_size);
if (max_cached_files>=-1)
_bioCache.setMaxCachedFiles(max_cached_files);
_bioCache.start();
}
}
if (_nioCache==null)
_bioCache=null;
if (max_cache_size!=-1 || max_cached_file_size!= -2 || max_cached_files!=-2)
_servletContext.log("ignoring resource cache configuration, using resourceCache attribute");
if (_relativeResourceBase!=null || _resourceBase!=null)
throw new UnavailableException("resourceCache specified with resource bases");
_cache=(ResourceCache)_servletContext.getAttribute(resourceCache);
if (_cache==null)
throw new UnavailableException("Could not find resourceCache "+resourceCache);
}
catch (Exception e)
else
{
Log.warn(Log.EXCEPTION,e);
throw new UnavailableException(e.toString());
try
{
if (max_cached_files>0)
{
_cache= new ResourceCache(this,_mimeTypes,_useFileMappedBuffer);
if (max_cache_size>0)
_cache.setMaxCacheSize(max_cache_size);
if (max_cached_file_size>=-1)
_cache.setMaxCachedFileSize(max_cached_file_size);
if (max_cached_files>=-1)
_cache.setMaxCachedFiles(max_cached_files);
}
}
catch (Exception e)
{
Log.warn(Log.EXCEPTION,e);
throw new UnavailableException(e.toString());
}
}
_servletHandler= (ServletHandler) _contextHandler.getChildHandlerByClass(ServletHandler.class);
@ -332,13 +324,14 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
}
/* ------------------------------------------------------------ */
@SuppressWarnings("unchecked")
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String servletPath=null;
String pathInfo=null;
Enumeration reqRanges = null;
Enumeration<String> reqRanges = null;
Boolean included =request.getAttribute(Dispatcher.INCLUDE_REQUEST_URI)!=null;
if (included!=null && included.booleanValue())
{
@ -378,9 +371,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
// Find the resource and content
Resource resource=null;
HttpContent content=null;
Connector connector = HttpConnection.getCurrentConnection().getConnector();
ResourceCache cache=(connector instanceof NIOConnector && !(connector instanceof SslConnector)) ?_nioCache:_bioCache;
try
{
// Try gzipped content first
@ -388,27 +379,27 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
{
pathInContextGz=pathInContext+".gz";
if (cache==null)
if (_cache==null)
{
resource=getResource(pathInContextGz);
}
else
{
content=cache.lookup(pathInContextGz,this);
content=_cache.lookup(pathInContextGz);
if (content!=null)
resource=content.getResource();
else
else if (!(content instanceof ResourceCache.Miss))
resource=getResource(pathInContextGz);
}
if (resource==null || !resource.exists()|| resource.isDirectory())
{
if (cache!=null && content==null)
if (_cache!=null && content==null)
{
String real_path=_servletContext.getRealPath(pathInContextGz);
if (real_path!=null)
cache.miss(pathInContextGz,_contextHandler.newResource(real_path));
_cache.miss(pathInContextGz,_contextHandler.newResource(real_path));
}
gzip=false;
pathInContextGz=null;
@ -418,11 +409,11 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
// find resource
if (!gzip)
{
if (cache==null)
if (_cache==null)
resource=getResource(pathInContext);
else
{
content=cache.lookup(pathInContext,this);
content=_cache.lookup(pathInContext);
if (content!=null)
resource=content.getResource();
@ -544,7 +535,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
}
/* ------------------------------------------------------------ */
private boolean hasDefinedRange(Enumeration reqRanges)
private boolean hasDefinedRange(Enumeration<String> reqRanges)
{
return (reqRanges!=null && reqRanges.hasMoreElements());
}
@ -723,8 +714,21 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
Enumeration reqRanges)
throws IOException
{
long content_length=content==null?resource.length():content.getContentLength();
boolean direct;
long content_length;
if (content==null)
{
direct=false;
content_length=resource.length();
}
else
{
Connector connector = HttpConnection.getCurrentConnection().getConnector();
direct=connector instanceof NIOConnector && ((NIOConnector)connector).getUseDirectBuffers() && !(connector instanceof SslConnector);
content_length=content.getContentLength();
}
// Get the output stream (or writer)
OutputStream out =null;
try{out = response.getOutputStream();}
@ -740,29 +744,39 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
else
{
// See if a direct methods can be used?
if (out instanceof HttpConnection.Output)
if (out instanceof HttpConnection.Output && content!=null)
{
if (response instanceof Response)
{
writeOptionHeaders(((Response)response).getHttpFields());
((HttpConnection.Output)out).sendContent(content);
}
else if (content.getBuffer()!=null)
else
{
writeHeaders(response,content,content_length);
((HttpConnection.Output)out).sendContent(content.getBuffer());
}
else
{
writeHeaders(response,content,content_length);
resource.writeTo(out,0,content_length);
Buffer buffer = direct?content.getDirectBuffer():content.getIndirectBuffer();
if (buffer!=null)
{
writeHeaders(response,content,content_length);
((HttpConnection.Output)out).sendContent(buffer);
}
else
{
writeHeaders(response,content,content_length);
resource.writeTo(out,0,content_length);
}
}
}
else
else
{
// Write content normally
// Write headers normally
writeHeaders(response,content,content_length);
resource.writeTo(out,0,content_length);
// Write content normally
Buffer buffer = (content==null)?null:content.getIndirectBuffer();
if (buffer!=null)
buffer.writeTo(out);
else
resource.writeTo(out,0,content_length);
}
}
}
@ -944,31 +958,9 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
@Override
public void destroy()
{
try
{
if (_nioCache!=null)
_nioCache.stop();
}
catch(Exception e)
{
Log.warn(Log.EXCEPTION,e);
}
finally
{
try
{
if (_bioCache!=null)
_bioCache.stop();
}
catch(Exception e)
{
Log.warn(Log.EXCEPTION,e);
}
finally
{
super.destroy();
}
}
if (_cache!=null)
_cache.flushCache();
super.destroy();
}
/* ------------------------------------------------------------ */
@ -996,7 +988,13 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
}
/* ------------------------------------------------------------ */
public Buffer getBuffer()
public Buffer getDirectBuffer()
{
return null;
}
/* ------------------------------------------------------------ */
public Buffer getIndirectBuffer()
{
return null;
}

View File

@ -1,86 +0,0 @@
// ========================================================================
// Copyright (c) 2004-2009 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.servlet;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
import org.eclipse.jetty.io.nio.NIOBuffer;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.ResourceCache;
import org.eclipse.jetty.server.nio.NIOConnector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
class NIOResourceCache extends ResourceCache
{
boolean _useFileMappedBuffer;
/* ------------------------------------------------------------ */
public NIOResourceCache(MimeTypes mimeTypes)
{
super(mimeTypes);
}
/* ------------------------------------------------------------ */
protected void fill(Content content) throws IOException
{
Buffer buffer=null;
Resource resource=content.getResource();
long length=resource.length();
if (_useFileMappedBuffer && resource.getFile()!=null)
{
buffer = new DirectNIOBuffer(resource.getFile());
}
else
{
InputStream is = resource.getInputStream();
try
{
Connector connector = HttpConnection.getCurrentConnection().getConnector();
buffer = ((NIOConnector)connector).getUseDirectBuffers()?
(NIOBuffer)new DirectNIOBuffer((int)length):
(NIOBuffer)new IndirectNIOBuffer((int)length);
}
catch(OutOfMemoryError e)
{
Log.warn(e.toString());
Log.debug(e);
buffer = new IndirectNIOBuffer((int) length);
}
buffer.readFrom(is,(int)length);
is.close();
}
content.setBuffer(buffer);
}
public boolean isUseFileMappedBuffer()
{
return _useFileMappedBuffer;
}
public void setUseFileMappedBuffer(boolean useFileMappedBuffer)
{
_useFileMappedBuffer = useFileMappedBuffer;
}
}

View File

@ -595,25 +595,6 @@ public class ServletHandler extends ScopedHandler
return chain;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the initializeAtStart.
* @deprecated
*/
public boolean isInitializeAtStart()
{
return false;
}
/* ------------------------------------------------------------ */
/**
* @param initializeAtStart The initializeAtStart to set.
* @deprecated
*/
public void setInitializeAtStart(boolean initializeAtStart)
{
}
/* ------------------------------------------------------------ */
/**
* @return true if the handler is started and there are no unavailable servlets
@ -719,7 +700,7 @@ public class ServletHandler extends ScopedHandler
}
/* ------------------------------------------------------------ */
public ServletHolder newServletHolder(Class servlet)
public ServletHolder newServletHolder(Class<? extends Servlet> servlet)
{
return new ServletHolder(servlet);
}
@ -782,18 +763,6 @@ public class ServletHandler extends ScopedHandler
}
}
/* ------------------------------------------------------------ */
/** Convenience method to add a servlet with a servlet mapping.
* @param className
* @param pathSpec
* @return the ServletHolder
* @deprecated use {@link #addServletWithMapping(Class, String)} instead
*/
public ServletHolder addServlet (String className, String pathSpec)
{
return addServletWithMapping (className, pathSpec);
}
/* ------------------------------------------------------------ */
/**Convenience method to add a pre-constructed ServletHolder.
@ -901,19 +870,6 @@ public class ServletHandler extends ScopedHandler
}
/* ------------------------------------------------------------ */
/** Convenience method to add a filter with a mapping
* @param className
* @param pathSpec
* @param dispatches
* @return the filter holder created
* @deprecated use {@link #addFilterWithMapping(Class, String, int)} instead
*/
public FilterHolder addFilter (String className,String pathSpec,int dispatches)
{
return addFilterWithMapping(className, pathSpec, dispatches);
}
/* ------------------------------------------------------------ */
/**
* convenience method to add a filter and mapping
@ -1325,6 +1281,7 @@ public class ServletHandler extends ScopedHandler
_maxFilterChainsCacheSize = maxFilterChainsCacheSize;
}
/* ------------------------------------------------------------ */
/**
* Customize a servlet.
*
@ -1342,14 +1299,14 @@ public class ServletHandler extends ScopedHandler
return servlet;
}
/* ------------------------------------------------------------ */
public Servlet customizeServletDestroy (Servlet servlet)
throws Exception
{
return servlet;
}
/* ------------------------------------------------------------ */
/**
* Customize a Filter.
*
@ -1357,9 +1314,9 @@ public class ServletHandler extends ScopedHandler
* Subclasses of ServletHandler should override
* this method.
*
* @param filter
* @param filter The filter to customize.
* @return the potentially customized filter
* @throws Exception
* @throws Exception If there was a problem
*/
public Filter customizeFilter (Filter filter)
throws Exception
@ -1367,7 +1324,7 @@ public class ServletHandler extends ScopedHandler
return filter;
}
/* ------------------------------------------------------------ */
public Filter customizeFilterDestroy (Filter filter)
throws Exception
{
@ -1375,8 +1332,8 @@ public class ServletHandler extends ScopedHandler
}
/* ------------------------------------------------------------ */
@Override
protected void dump(StringBuilder b,String indent)
{
super.dump(b,indent);
@ -1423,6 +1380,4 @@ public class ServletHandler extends ScopedHandler
}
}
}

View File

@ -27,16 +27,14 @@ import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
class JarFileResource extends JarResource
{
transient JarFile _jarFile;
transient File _file;
transient String[] _list;
transient JarEntry _entry;
transient boolean _directory;
transient String _jarUrl;
transient String _path;
transient boolean _exists;
private JarFile _jarFile;
private File _file;
private String[] _list;
private JarEntry _entry;
private boolean _directory;
private String _jarUrl;
private String _path;
private boolean _exists;
/* -------------------------------------------------------- */
JarFileResource(URL url)
@ -44,6 +42,7 @@ class JarFileResource extends JarResource
super(url);
}
/* ------------------------------------------------------------ */
JarFileResource(URL url, boolean useCaches)
{
super(url, useCaches);
@ -65,7 +64,8 @@ class JarFileResource extends JarResource
@Override
protected boolean checkConnection()
{
try{
try
{
super.checkConnection();
}
finally
@ -84,7 +84,7 @@ class JarFileResource extends JarResource
/* ------------------------------------------------------------ */
@Override
protected void newConnection()
protected synchronized void newConnection()
throws IOException
{
super.newConnection();

View File

@ -31,8 +31,7 @@ import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
public class JarResource extends URLResource
{
protected transient JarURLConnection _jarConnection;
protected JarURLConnection _jarConnection;
/* -------------------------------------------------------- */
JarResource(URL url)
@ -56,7 +55,7 @@ public class JarResource extends URLResource
/* ------------------------------------------------------------ */
@Override
protected boolean checkConnection()
protected synchronized boolean checkConnection()
{
super.checkConnection();
try
@ -120,16 +119,6 @@ public class JarResource extends URLResource
InputStream is = url.openStream();
return is;
}
/* ------------------------------------------------------------ */
@Deprecated
public void extract(File dest, boolean deleteOnExit)
throws IOException
{
if (deleteOnExit)
dest.deleteOnExit();
copyTo(dest);
}
/* ------------------------------------------------------------ */
@Override

View File

@ -37,10 +37,10 @@ import org.eclipse.jetty.util.log.Log;
/**
* Abstract resource class.
*/
public abstract class Resource implements Serializable
public abstract class Resource
{
public static boolean __defaultUseCaches = true;
Object _associate;
volatile Object _associate;
/**
* Change the default setting for url connection caches.
@ -51,7 +51,8 @@ public abstract class Resource implements Serializable
{
__defaultUseCaches=useCaches;
}
/* ------------------------------------------------------------ */
public static boolean getDefaultUseCaches ()
{
return __defaultUseCaches;
@ -61,6 +62,7 @@ public abstract class Resource implements Serializable
/** Construct a resource from a uri.
* @param uri A URI.
* @return A Resource object.
* @throws IOException Problem accessing URI
*/
public static Resource newResource(URI uri)
throws IOException
@ -72,6 +74,7 @@ public abstract class Resource implements Serializable
/** Construct a resource from a url.
* @param url A URL.
* @return A Resource object.
* @throws IOException Problem accessing URL
*/
public static Resource newResource(URL url)
throws IOException
@ -199,6 +202,9 @@ public abstract class Resource implements Serializable
/** Construct a system resource from a string.
* The resource is tried as classloader resource before being
* treated as a normal resource.
* @param resource Resource as string representation
* @return The new Resource
* @throws IOException Problem accessing resource.
*/
public static Resource newSystemResource(String resource)
throws IOException
@ -287,6 +293,7 @@ public abstract class Resource implements Serializable
return newResource(url,useCaches);
}
/* ------------------------------------------------------------ */
public static boolean isContainedIn (Resource r, Resource containingResource) throws MalformedURLException
{
return r.isContainedIn(containingResource);
@ -298,12 +305,13 @@ public abstract class Resource implements Serializable
{
release();
}
/* ------------------------------------------------------------ */
public abstract boolean isContainedIn (Resource r) throws MalformedURLException;
/* ------------------------------------------------------------ */
/** Release any resources held by the resource.
/** Release any temporary resources held by the resource.
*/
public abstract void release();

View File

@ -32,12 +32,11 @@ import org.eclipse.jetty.util.log.Log;
*/
public class URLResource extends Resource
{
protected URL _url;
protected final URL _url;
protected String _urlString;
protected transient URLConnection _connection;
protected transient InputStream _in=null;
protected URLConnection _connection;
protected InputStream _in=null;
transient boolean _useCaches = Resource.__defaultUseCaches;
/* ------------------------------------------------------------ */
@ -48,6 +47,7 @@ public class URLResource extends Resource
_connection=connection;
}
/* ------------------------------------------------------------ */
protected URLResource (URL url, URLConnection connection, boolean useCaches)
{
this (url, connection);

View File

@ -125,7 +125,21 @@ public class QueuedThreadPool extends AbstractLifeCycle implements ThreadPool, E
Thread.yield();
int size=_threads.size();
if (size>0)
{
Log.warn(size+" threads could not be stopped");
if (Log.isDebugEnabled())
{
for (Thread unstopped : _threads)
{
Log.debug("Couldn't stop "+unstopped);
for (StackTraceElement element : unstopped.getStackTrace())
{
Log.debug(" at "+element);
}
}
}
}
synchronized (_joinLock)
{

View File

@ -93,7 +93,7 @@
</filter>
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>/*</url-pattern>
<url-pattern>/dump/gzip/*</url-pattern>
</filter-mapping>

View File

@ -22,6 +22,7 @@ import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
@ -37,7 +38,7 @@ public class TestServer
{
public static void main(String[] args) throws Exception
{
Log.getLog().setDebugEnabled(true);
Log.getLog().setDebugEnabled(false);
((StdErrLog)Log.getLog()).setSource(false);
String jetty_root = "..";
@ -50,7 +51,6 @@ public class TestServer
server.getContainer().addEventListener(mbContainer);
server.addBean(mbContainer);
mbContainer.addBean(Log.getLog());
// Setup Threadpool
QueuedThreadPool threadPool = new QueuedThreadPool();
@ -58,12 +58,27 @@ public class TestServer
server.setThreadPool(threadPool);
// Setup Connectors
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(8080);
connector.setMaxIdleTime(30000);
connector.setConfidentialPort(8443);
server.setConnectors(new Connector[]
{ connector });
SelectChannelConnector connector0 = new SelectChannelConnector();
connector0.setPort(8080);
connector0.setMaxIdleTime(30000);
connector0.setConfidentialPort(8443);
connector0.setUseDirectBuffers(true);
server.addConnector(connector0);
// Setup Connectors
SelectChannelConnector connector1 = new SelectChannelConnector();
connector1.setPort(8081);
connector1.setMaxIdleTime(30000);
connector1.setConfidentialPort(8443);
connector1.setUseDirectBuffers(false);
server.addConnector(connector1);
// Setup Connectors
SocketConnector connector2 = new SocketConnector();
connector2.setPort(8082);
connector2.setMaxIdleTime(30000);
connector2.setConfidentialPort(8443);
server.addConnector(connector2);
SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector();
ssl_connector.setPort(8443);