Issue #485 Multiple compressed formats from static content

Renamed ResourceCache as per TODO
Added javadoc and XML comments
This commit is contained in:
Greg Wilkins 2016-04-07 17:33:47 +10:00
parent a72838162d
commit 2fb9b55da2
6 changed files with 67 additions and 33 deletions

View File

@ -40,4 +40,18 @@ public class CompressedContentFormat
_etagQuote = _etag + "\""; _etagQuote = _etag + "\"";
_contentEncoding = new PreEncodedHttpField(HttpHeader.CONTENT_ENCODING, encoding); _contentEncoding = new PreEncodedHttpField(HttpHeader.CONTENT_ENCODING, encoding);
} }
@Override
public boolean equals(Object o)
{
if (!(o instanceof CompressedContentFormat))
return false;
CompressedContentFormat ccf = (CompressedContentFormat)o;
if (_encoding==null && ccf._encoding!=null)
return false;
if (_extension==null && ccf._extension!=null)
return false;
return _encoding.equalsIgnoreCase(ccf._encoding) && _extension.equalsIgnoreCase(ccf._extension);
}
} }

View File

@ -49,16 +49,18 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.resource.ResourceFactory;
// TODO rename to ContentCache /**
public class ResourceCache implements HttpContent.Factory * Caching HttpContent.Factory
*/
public class CachedContentFactory implements HttpContent.Factory
{ {
private static final Logger LOG = Log.getLogger(ResourceCache.class); private static final Logger LOG = Log.getLogger(CachedContentFactory.class);
private final ConcurrentMap<String,CachedHttpContent> _cache; private final ConcurrentMap<String,CachedHttpContent> _cache;
private final AtomicInteger _cachedSize; private final AtomicInteger _cachedSize;
private final AtomicInteger _cachedFiles; private final AtomicInteger _cachedFiles;
private final ResourceFactory _factory; private final ResourceFactory _factory;
private final ResourceCache _parent; private final CachedContentFactory _parent;
private final MimeTypes _mimeTypes; private final MimeTypes _mimeTypes;
private final boolean _etags; private final boolean _etags;
private final CompressedContentFormat[] _precompressedFormats; private final CompressedContentFormat[] _precompressedFormats;
@ -77,7 +79,7 @@ public class ResourceCache implements HttpContent.Factory
* @param etags true to support etags * @param etags true to support etags
* @param precompressedFormats array of precompression formats to support * @param precompressedFormats array of precompression formats to support
*/ */
public ResourceCache(ResourceCache parent, ResourceFactory factory, MimeTypes mimeTypes,boolean useFileMappedBuffer,boolean etags,CompressedContentFormat[] precompressedFormats) public CachedContentFactory(CachedContentFactory parent, ResourceFactory factory, MimeTypes mimeTypes,boolean useFileMappedBuffer,boolean etags,CompressedContentFormat[] precompressedFormats)
{ {
_factory = factory; _factory = factory;
_cache=new ConcurrentHashMap<String,CachedHttpContent>(); _cache=new ConcurrentHashMap<String,CachedHttpContent>();
@ -442,7 +444,7 @@ public class ResourceCache implements HttpContent.Factory
_lastAccessed=System.currentTimeMillis(); _lastAccessed=System.currentTimeMillis();
_etag=ResourceCache.this._etags?new PreEncodedHttpField(HttpHeader.ETAG,resource.getWeakETag()):null; _etag=CachedContentFactory.this._etags?new PreEncodedHttpField(HttpHeader.ETAG,resource.getWeakETag()):null;
if (precompressedResources != null) if (precompressedResources != null)
{ {
@ -596,7 +598,7 @@ public class ResourceCache implements HttpContent.Factory
ByteBuffer buffer = _indirectBuffer.get(); ByteBuffer buffer = _indirectBuffer.get();
if (buffer==null) if (buffer==null)
{ {
ByteBuffer buffer2=ResourceCache.this.getIndirectBuffer(_resource); ByteBuffer buffer2=CachedContentFactory.this.getIndirectBuffer(_resource);
if (buffer2==null) if (buffer2==null)
LOG.warn("Could not load "+this); LOG.warn("Could not load "+this);
@ -621,7 +623,7 @@ public class ResourceCache implements HttpContent.Factory
ByteBuffer buffer = _directBuffer.get(); ByteBuffer buffer = _directBuffer.get();
if (buffer==null) if (buffer==null)
{ {
ByteBuffer buffer2=ResourceCache.this.getDirectBuffer(_resource); ByteBuffer buffer2=CachedContentFactory.this.getDirectBuffer(_resource);
if (buffer2==null) if (buffer2==null)
LOG.warn("Could not load "+this); LOG.warn("Could not load "+this);
@ -714,7 +716,7 @@ public class ResourceCache implements HttpContent.Factory
_content=content; _content=content;
_precompressedContent=precompressedContent; _precompressedContent=precompressedContent;
_etag=(ResourceCache.this._etags)?new PreEncodedHttpField(HttpHeader.ETAG,_content.getResource().getWeakETag(format._etag)):null; _etag=(CachedContentFactory.this._etags)?new PreEncodedHttpField(HttpHeader.ETAG,_content.getResource().getWeakETag(format._etag)):null;
} }
public boolean isValid() public boolean isValid()

View File

@ -32,7 +32,7 @@ import org.eclipse.jetty.util.resource.ResourceFactory;
/** /**
* A HttpContent.Factory for transient content. The HttpContent's created by * A HttpContent.Factory for transient content (not cached). The HttpContent's created by
* this factory are not intended to be cached, so memory limits for individual * this factory are not intended to be cached, so memory limits for individual
* HttpOutput streams are enforced. * HttpOutput streams are enforced.
*/ */

View File

@ -51,9 +51,9 @@ public class ResourceCacheTest
Resource[] r = rc.getResources(); Resource[] r = rc.getResources();
MimeTypes mime = new MimeTypes(); MimeTypes mime = new MimeTypes();
ResourceCache rc3 = new ResourceCache(null,r[2],mime,false,false,CompressedContentFormat.NONE); CachedContentFactory rc3 = new CachedContentFactory(null,r[2],mime,false,false,CompressedContentFormat.NONE);
ResourceCache rc2 = new ResourceCache(rc3,r[1],mime,false,false,CompressedContentFormat.NONE); CachedContentFactory rc2 = new CachedContentFactory(rc3,r[1],mime,false,false,CompressedContentFormat.NONE);
ResourceCache rc1 = new ResourceCache(rc2,r[0],mime,false,false,CompressedContentFormat.NONE); CachedContentFactory rc1 = new CachedContentFactory(rc2,r[0],mime,false,false,CompressedContentFormat.NONE);
assertEquals("1 - one", getContent(rc1, "1.txt")); assertEquals("1 - one", getContent(rc1, "1.txt"));
assertEquals("2 - two", getContent(rc1, "2.txt")); assertEquals("2 - two", getContent(rc1, "2.txt"));
@ -81,8 +81,8 @@ public class ResourceCacheTest
Resource[] r = rc.getResources(); Resource[] r = rc.getResources();
MimeTypes mime = new MimeTypes(); MimeTypes mime = new MimeTypes();
ResourceCache rc3 = new ResourceCache(null,r[2],mime,false,false,CompressedContentFormat.NONE); CachedContentFactory rc3 = new CachedContentFactory(null,r[2],mime,false,false,CompressedContentFormat.NONE);
ResourceCache rc2 = new ResourceCache(rc3,r[1],mime,false,false,CompressedContentFormat.NONE) CachedContentFactory rc2 = new CachedContentFactory(rc3,r[1],mime,false,false,CompressedContentFormat.NONE)
{ {
@Override @Override
public boolean isCacheable(Resource resource) public boolean isCacheable(Resource resource)
@ -91,7 +91,7 @@ public class ResourceCacheTest
} }
}; };
ResourceCache rc1 = new ResourceCache(rc2,r[0],mime,false,false,CompressedContentFormat.NONE); CachedContentFactory rc1 = new CachedContentFactory(rc2,r[0],mime,false,false,CompressedContentFormat.NONE);
assertEquals("1 - one", getContent(rc1, "1.txt")); assertEquals("1 - one", getContent(rc1, "1.txt"));
assertEquals("2 - two", getContent(rc1, "2.txt")); assertEquals("2 - two", getContent(rc1, "2.txt"));
@ -114,7 +114,7 @@ public class ResourceCacheTest
final Resource directory; final Resource directory;
File[] files=new File[10]; File[] files=new File[10];
String[] names=new String[files.length]; String[] names=new String[files.length];
ResourceCache cache; CachedContentFactory cache;
for (int i=0;i<files.length;i++) for (int i=0;i<files.length;i++)
{ {
@ -132,7 +132,7 @@ public class ResourceCacheTest
directory=Resource.newResource(files[0].getParentFile().getAbsolutePath()); directory=Resource.newResource(files[0].getParentFile().getAbsolutePath());
cache=new ResourceCache(null,directory,new MimeTypes(),false,false,CompressedContentFormat.NONE); cache=new CachedContentFactory(null,directory,new MimeTypes(),false,false,CompressedContentFormat.NONE);
cache.setMaxCacheSize(95); cache.setMaxCacheSize(95);
cache.setMaxCachedFileSize(85); cache.setMaxCachedFileSize(85);
@ -159,7 +159,7 @@ public class ResourceCacheTest
assertEquals(0,cache.getCachedSize()); assertEquals(0,cache.getCachedSize());
assertEquals(0,cache.getCachedFiles()); assertEquals(0,cache.getCachedFiles());
cache=new ResourceCache(null,directory,new MimeTypes(),true,false,CompressedContentFormat.NONE); cache=new CachedContentFactory(null,directory,new MimeTypes(),true,false,CompressedContentFormat.NONE);
cache.setMaxCacheSize(95); cache.setMaxCacheSize(95);
cache.setMaxCachedFileSize(85); cache.setMaxCachedFileSize(85);
cache.setMaxCachedFiles(4); cache.setMaxCachedFiles(4);
@ -284,7 +284,7 @@ public class ResourceCacheTest
Resource[] resources = rc.getResources(); Resource[] resources = rc.getResources();
MimeTypes mime = new MimeTypes(); MimeTypes mime = new MimeTypes();
ResourceCache cache = new ResourceCache(null,resources[0],mime,false,false,CompressedContentFormat.NONE); CachedContentFactory cache = new CachedContentFactory(null,resources[0],mime,false,false,CompressedContentFormat.NONE);
assertEquals("4 - four", getContent(cache, "four.txt")); assertEquals("4 - four", getContent(cache, "four.txt"));
assertEquals("4 - four (no extension)", getContent(cache, "four")); assertEquals("4 - four (no extension)", getContent(cache, "four"));
@ -303,7 +303,7 @@ public class ResourceCacheTest
return buffer.toString(); return buffer.toString();
} }
static String getContent(ResourceCache rc, String path) throws Exception static String getContent(CachedContentFactory rc, String path) throws Exception
{ {
HttpContent content = rc.lookup(path); HttpContent content = rc.lookup(path);
if (content==null) if (content==null)

View File

@ -37,7 +37,7 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http.pathmap.MappedResource; import org.eclipse.jetty.http.pathmap.MappedResource;
import org.eclipse.jetty.server.ResourceCache; import org.eclipse.jetty.server.CachedContentFactory;
import org.eclipse.jetty.server.ResourceContentFactory; import org.eclipse.jetty.server.ResourceContentFactory;
import org.eclipse.jetty.server.ResourceService; import org.eclipse.jetty.server.ResourceService;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
@ -78,7 +78,14 @@ import org.eclipse.jetty.util.resource.ResourceFactory;
* *
* gzip If set to true, then static content will be served as * gzip If set to true, then static content will be served as
* gzip content encoded if a matching resource is * gzip content encoded if a matching resource is
* found ending with ".gz" * found ending with ".gz" (default false)
* (deprecated: use precompressed)
*
* precompressed If set to a comma separated list of file extensions, these
* indicate compressed formats that are known to map to a mime-type
* that may be listed in a requests Accept-Encoding header.
* If set to a boolean True, then a default set of compressed formats
* will be used, otherwise no precompressed formats.
* *
* resourceBase Set to replace the context resource base * resourceBase Set to replace the context resource base
* *
@ -111,8 +118,8 @@ import org.eclipse.jetty.util.resource.ResourceFactory;
* cacheControl If set, all static content will have this value set as the cache-control * cacheControl If set, all static content will have this value set as the cache-control
* header. * header.
* *
* otherGzipFileExtensions * otherGzipFileExtensions
* Other file extensions that signify that a file is gzip compressed. Eg ".svgz" * Other file extensions that signify that a file is already compressed. Eg ".svgz"
* *
* *
* </pre> * </pre>
@ -132,7 +139,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
private boolean _welcomeExactServlets=false; private boolean _welcomeExactServlets=false;
private Resource _resourceBase; private Resource _resourceBase;
private ResourceCache _cache; private CachedContentFactory _cache;
private MimeTypes _mimeTypes; private MimeTypes _mimeTypes;
private String[] _welcomes; private String[] _welcomes;
@ -264,14 +271,14 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
LOG.debug("ignoring resource cache configuration, using resourceCache attribute"); LOG.debug("ignoring resource cache configuration, using resourceCache attribute");
if (_relativeResourceBase!=null || _resourceBase!=null) if (_relativeResourceBase!=null || _resourceBase!=null)
throw new UnavailableException("resourceCache specified with resource bases"); throw new UnavailableException("resourceCache specified with resource bases");
_cache=(ResourceCache)_servletContext.getAttribute(resourceCache); _cache=(CachedContentFactory)_servletContext.getAttribute(resourceCache);
} }
try try
{ {
if (_cache==null && (max_cached_files!=-2 || max_cache_size!=-2 || max_cached_file_size!=-2)) if (_cache==null && (max_cached_files!=-2 || max_cache_size!=-2 || max_cached_file_size!=-2))
{ {
_cache = new ResourceCache(null,this,_mimeTypes,_useFileMappedBuffer,_resourceService.isEtags(),_resourceService.getPrecompressedFormats()); _cache = new CachedContentFactory(null,this,_mimeTypes,_useFileMappedBuffer,_resourceService.isEtags(),_resourceService.getPrecompressedFormats());
if (max_cache_size>=0) if (max_cache_size>=0)
_cache.setMaxCacheSize(max_cache_size); _cache.setMaxCacheSize(max_cache_size);
if (max_cached_file_size>=-1) if (max_cached_file_size>=-1)
@ -333,9 +340,11 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
for (String pair : precompressed.split(",")) for (String pair : precompressed.split(","))
{ {
String[] setting = pair.split("="); String[] setting = pair.split("=");
String encoding = setting[0]; String encoding = setting[0].trim();
String extension = setting[1]; String extension = setting[1].trim();
ret.add(new CompressedContentFormat(encoding,extension)); ret.add(new CompressedContentFormat(encoding,extension));
if (gzip && !ret.contains(CompressedContentFormat.GZIP))
ret.add(CompressedContentFormat.GZIP);
} }
} }
else if (precompressed != null) else if (precompressed != null)

View File

@ -92,7 +92,14 @@
* *
* gzip If set to true, then static content will be served as * gzip If set to true, then static content will be served as
* gzip content encoded if a matching resource is * gzip content encoded if a matching resource is
* found ending with ".gz" * found ending with ".gz" (default false)
* (deprecated: use precompressed)
*
* precompressed If set to a comma separated list of file extensions, these
* indicate compressed formats that are known to map to a mime-type
* that may be listed in a requests Accept-Encoding header.
* If set to a boolean True, then a default set of compressed formats
* will be used, otherwise no precompressed formats.
* *
* resourceBase Set to replace the context resource base * resourceBase Set to replace the context resource base
* *
@ -164,10 +171,12 @@
<param-name>maxCachedFiles</param-name> <param-name>maxCachedFiles</param-name>
<param-value>2048</param-value> <param-value>2048</param-value>
</init-param> </init-param>
<!--
<init-param> <init-param>
<param-name>gzip</param-name> <param-name>precompressed</param-name>
<param-value>false</param-value> <param-value>gzip,br</param-value>
</init-param> </init-param>
-->
<init-param> <init-param>
<param-name>etags</param-name> <param-name>etags</param-name>
<param-value>false</param-value> <param-value>false</param-value>