diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/CompressedContentFormat.java b/jetty-http/src/main/java/org/eclipse/jetty/http/CompressedContentFormat.java index b3ffd599662b..385dacf04e15 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/CompressedContentFormat.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/CompressedContentFormat.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.http; +import org.eclipse.jetty.util.StringUtil; + public class CompressedContentFormat { public static final CompressedContentFormat GZIP = new CompressedContentFormat("gzip", ".gz"); @@ -44,13 +46,9 @@ 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); + CompressedContentFormat ccf = (CompressedContentFormat)o; + return StringUtil.equalsIgnoreCase(_encoding, ccf._encoding) && StringUtil.equalsIgnoreCase(_extension, ccf._extension); } public static boolean tagEquals(String etag, String tag) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/ResourceHttpContent.java b/jetty-http/src/main/java/org/eclipse/jetty/http/ResourceHttpContent.java index a248c28d88ea..76b5cc441321 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/ResourceHttpContent.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/ResourceHttpContent.java @@ -22,11 +22,14 @@ import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.jetty.http.MimeTypes.Type; -import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.io.ByteBufferPoolUtil; import org.eclipse.jetty.util.resource.Resource; /** @@ -40,24 +43,31 @@ public class ResourceHttpContent implements HttpContent final Resource _resource; final String _contentType; final int _maxBuffer; - Map _precompressedContents; - String _etag; + final ByteBufferPool _bufferPool; + final Map _precompressedContents; + final List _allocatedBuffers = new ArrayList<>(); public ResourceHttpContent(final Resource resource, final String contentType) { - this(resource, contentType, -1, null); + this(resource, contentType, -1, null, null); } public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer) { - this(resource, contentType, maxBuffer, null); + this(resource, contentType, maxBuffer, null, null); } public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer, Map precompressedContents) + { + this(resource, contentType, maxBuffer, null, null); + } + + public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer, Map precompressedContents, ByteBufferPool bufferPool) { _resource = resource; _contentType = contentType; _maxBuffer = maxBuffer; + _bufferPool = bufferPool; if (precompressedContents == null) { _precompressedContents = null; @@ -122,21 +132,6 @@ public String getLastModifiedValue() return lm >= 0 ? DateGenerator.formatDate(lm) : null; } - @Override - public ByteBuffer getDirectBuffer() - { - if (_resource.length() <= 0 || _maxBuffer > 0 && _resource.length() > _maxBuffer) - return null; - try - { - return BufferUtil.toBuffer(_resource, true); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - @Override public HttpField getETag() { @@ -156,7 +151,26 @@ public ByteBuffer getIndirectBuffer() return null; try { - return BufferUtil.toBuffer(_resource, false); + ByteBuffer byteBuffer = ByteBufferPoolUtil.resourceToBuffer(_resource, false, _bufferPool); + _allocatedBuffers.add(byteBuffer); + return byteBuffer; + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + @Override + public ByteBuffer getDirectBuffer() + { + if (_resource.length() <= 0 || _maxBuffer > 0 && _resource.length() > _maxBuffer) + return null; + try + { + ByteBuffer byteBuffer = ByteBufferPoolUtil.resourceToBuffer(_resource, true, _bufferPool); + _allocatedBuffers.add(byteBuffer); + return byteBuffer; } catch (IOException e) { @@ -198,6 +212,15 @@ public Resource getResource() @Override public void release() { + if (_bufferPool != null) + { + for (ByteBuffer byteBuffer : _allocatedBuffers) + { + _bufferPool.release(byteBuffer); + } + } + + _allocatedBuffers.clear(); _resource.close(); } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ByteBufferPoolUtil.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ByteBufferPoolUtil.java new file mode 100644 index 000000000000..3245bd62f0aa --- /dev/null +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ByteBufferPoolUtil.java @@ -0,0 +1,63 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// ------------------------------------------------------------------------ +// 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; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; + +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.resource.Resource; + +public class ByteBufferPoolUtil +{ + public static ByteBuffer resourceToBuffer(Resource resource, boolean direct, ByteBufferPool bufferPool) throws IOException + { + long len = resource.length(); + if (len < 0) + throw new IllegalArgumentException("invalid resource: " + resource + " len=" + len); + + if (len > Integer.MAX_VALUE) + { + // This method cannot handle resources of this size. + return null; + } + + int ilen = (int)len; + ByteBuffer buffer; + if (bufferPool != null) + buffer = bufferPool.acquire(ilen, direct); + else + buffer = direct ? BufferUtil.allocateDirect(ilen) : BufferUtil.allocate(ilen); + + int pos = BufferUtil.flipToFill(buffer); + if (resource.getFile() != null) + BufferUtil.readFrom(resource.getFile(), buffer); + else + { + try (InputStream is = resource.getInputStream()) + { + BufferUtil.readFrom(is, ilen, buffer); + } + } + BufferUtil.flipToFlush(buffer, pos); + + return buffer; + } +} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/CachedContentFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/CachedContentFactory.java index 79bd5b979667..9d8fb9f9c5d5 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/CachedContentFactory.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/CachedContentFactory.java @@ -43,6 +43,8 @@ import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.http.PrecompressedHttpContent; import org.eclipse.jetty.http.ResourceHttpContent; +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.io.ByteBufferPoolUtil; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -63,6 +65,7 @@ public class CachedContentFactory implements HttpContent.ContentFactory private final boolean _etags; private final CompressedContentFormat[] _precompressedFormats; private final boolean _useFileMappedBuffer; + private final ByteBufferPool _bufferPool; private int _maxCachedFileSize = 128 * 1024 * 1024; private int _maxCachedFiles = 2048; @@ -79,6 +82,22 @@ public class CachedContentFactory implements HttpContent.ContentFactory * @param precompressedFormats array of precompression formats to support */ public CachedContentFactory(CachedContentFactory parent, ResourceFactory factory, MimeTypes mimeTypes, boolean useFileMappedBuffer, boolean etags, CompressedContentFormat[] precompressedFormats) + { + this(parent, factory, mimeTypes, useFileMappedBuffer, etags, precompressedFormats, null); + } + + /** + * Constructor. + * + * @param parent the parent resource cache + * @param factory the resource factory + * @param mimeTypes Mimetype to use for meta data + * @param useFileMappedBuffer true to file memory mapped buffers + * @param etags true to support etags + * @param precompressedFormats array of precompression formats to support + * @param bufferPool the ByteBufferPool to use + */ + public CachedContentFactory(CachedContentFactory parent, ResourceFactory factory, MimeTypes mimeTypes, boolean useFileMappedBuffer, boolean etags, CompressedContentFormat[] precompressedFormats, ByteBufferPool bufferPool) { _factory = factory; _cache = new ConcurrentHashMap<>(); @@ -89,6 +108,7 @@ public CachedContentFactory(CachedContentFactory parent, ResourceFactory factory _useFileMappedBuffer = useFileMappedBuffer; _etags = etags; _precompressedFormats = precompressedFormats; + _bufferPool = bufferPool; } public int getCachedSize() @@ -193,9 +213,7 @@ public HttpContent getContent(String pathInContext, int maxBufferSize) throws IO // Is the content in the parent cache? if (_parent != null) { - HttpContent httpContent = _parent.getContent(pathInContext, maxBufferSize); - if (httpContent != null) - return httpContent; + return _parent.getContent(pathInContext, maxBufferSize); } return null; @@ -222,7 +240,7 @@ private HttpContent load(String pathInContext, Resource resource, int maxBufferS return null; if (resource.isDirectory()) - return new ResourceHttpContent(resource, _mimeTypes.getMimeByExtension(resource.toString()), getMaxCachedFileSize()); + return new ResourceHttpContent(resource, _mimeTypes.getMimeByExtension(resource.toString()), getMaxCachedFileSize(), null, _bufferPool); // Will it fit in the cache? if (isCacheable(resource)) @@ -237,7 +255,7 @@ private HttpContent load(String pathInContext, Resource resource, int maxBufferS { String compressedPathInContext = pathInContext + format._extension; CachedHttpContent compressedContent = _cache.get(compressedPathInContext); - if (compressedContent == null || compressedContent.isValid()) + if (compressedContent == null || !compressedContent.isValid()) { compressedContent = null; Resource compressedResource = _factory.getResource(compressedPathInContext); @@ -290,13 +308,13 @@ private HttpContent load(String pathInContext, Resource resource, int maxBufferS if (compressedResource.exists() && compressedResource.lastModified() >= resource.lastModified() && compressedResource.length() < resource.length()) compressedContents.put(format, - new ResourceHttpContent(compressedResource, _mimeTypes.getMimeByExtension(compressedPathInContext), maxBufferSize)); + new ResourceHttpContent(compressedResource, _mimeTypes.getMimeByExtension(compressedPathInContext), maxBufferSize, null, _bufferPool)); } if (!compressedContents.isEmpty()) - return new ResourceHttpContent(resource, mt, maxBufferSize, compressedContents); + return new ResourceHttpContent(resource, mt, maxBufferSize, compressedContents, _bufferPool); } - return new ResourceHttpContent(resource, mt, maxBufferSize); + return new ResourceHttpContent(resource, mt, maxBufferSize, null, _bufferPool); } private void shrinkCache() @@ -335,7 +353,7 @@ protected ByteBuffer getIndirectBuffer(Resource resource) { try { - return BufferUtil.toBuffer(resource, false); + return ByteBufferPoolUtil.resourceToBuffer(resource, false, _bufferPool); } catch (IOException | IllegalArgumentException e) { @@ -366,7 +384,7 @@ protected ByteBuffer getDirectBuffer(Resource resource) { try { - return BufferUtil.toBuffer(resource, true); + return ByteBufferPoolUtil.resourceToBuffer(resource, true, _bufferPool); } catch (IOException | IllegalArgumentException e) { @@ -485,6 +503,8 @@ boolean isValid() protected void invalidate() { + release(); + ByteBuffer indirect = _indirectBuffer.getAndSet(null); if (indirect != null) _cachedSize.addAndGet(-BufferUtil.length(indirect)); @@ -550,6 +570,16 @@ public Type getMimeType() @Override public void release() { + if (_bufferPool != null) + { + ByteBuffer indirectBuffer = _indirectBuffer.get(); + if (indirectBuffer != null) + _bufferPool.release(indirectBuffer); + + ByteBuffer directBuffer = _directBuffer.get(); + if (directBuffer != null) + _bufferPool.release(directBuffer); + } } @Override @@ -579,10 +609,11 @@ public ByteBuffer getIndirectBuffer() } else { + _bufferPool.release(buffer2); buffer = _indirectBuffer.get(); } } - return buffer == null ? null : buffer.asReadOnlyBuffer(); + return buffer.slice(); } @Override @@ -615,6 +646,7 @@ else if (_resource.length() < _maxCachedFileSize) } else { + _bufferPool.release(direct); buffer = _directBuffer.get(); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceContentFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceContentFactory.java index e29e68b3981f..5bd0fe217419 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceContentFactory.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceContentFactory.java @@ -28,6 +28,7 @@ import org.eclipse.jetty.http.HttpContent.ContentFactory; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.ResourceHttpContent; +import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.ResourceFactory; @@ -41,12 +42,19 @@ public class ResourceContentFactory implements ContentFactory private final ResourceFactory _factory; private final MimeTypes _mimeTypes; private final CompressedContentFormat[] _precompressedFormats; + private final ByteBufferPool _bufferPool; public ResourceContentFactory(ResourceFactory factory, MimeTypes mimeTypes, CompressedContentFormat[] precompressedFormats) + { + this(factory, mimeTypes, precompressedFormats, null); + } + + public ResourceContentFactory(ResourceFactory factory, MimeTypes mimeTypes, CompressedContentFormat[] precompressedFormats, ByteBufferPool bufferPool) { _factory = factory; _mimeTypes = mimeTypes; _precompressedFormats = precompressedFormats; + _bufferPool = bufferPool; } @Override @@ -57,8 +65,7 @@ public HttpContent getContent(String pathInContext, int maxBufferSize) { // try loading the content from our factory. Resource resource = _factory.getResource(pathInContext); - HttpContent loaded = load(pathInContext, resource, maxBufferSize); - return loaded; + return load(pathInContext, resource, maxBufferSize); } catch (Throwable t) { @@ -74,7 +81,7 @@ private HttpContent load(String pathInContext, Resource resource, int maxBufferS return null; if (resource.isDirectory()) - return new ResourceHttpContent(resource, _mimeTypes.getMimeByExtension(resource.toString()), maxBufferSize); + return new ResourceHttpContent(resource, _mimeTypes.getMimeByExtension(resource.toString()), maxBufferSize, null, _bufferPool); // Look for a precompressed resource or content String mt = _mimeTypes.getMimeByExtension(pathInContext); @@ -89,12 +96,12 @@ private HttpContent load(String pathInContext, Resource resource, int maxBufferS if (compressedResource != null && compressedResource.exists() && compressedResource.lastModified() >= resource.lastModified() && compressedResource.length() < resource.length()) compressedContents.put(format, - new ResourceHttpContent(compressedResource, _mimeTypes.getMimeByExtension(compressedPathInContext), maxBufferSize)); + new ResourceHttpContent(compressedResource, _mimeTypes.getMimeByExtension(compressedPathInContext), maxBufferSize, null, _bufferPool)); } if (!compressedContents.isEmpty()) - return new ResourceHttpContent(resource, mt, maxBufferSize, compressedContents); + return new ResourceHttpContent(resource, mt, maxBufferSize, compressedContents, _bufferPool); } - return new ResourceHttpContent(resource, mt, maxBufferSize); + return new ResourceHttpContent(resource, mt, maxBufferSize, null, _bufferPool); } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index 8a2854d05c22..d7e575c4c9a4 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -74,7 +74,7 @@ public class ResourceService private boolean _acceptRanges = true; private boolean _dirAllowed = true; private boolean _redirectWelcome = false; - private CompressedContentFormat[] _precompressedFormats = new CompressedContentFormat[0]; + private CompressedContentFormat[] _precompressedFormats = CompressedContentFormat.NONE; private String[] _preferredEncodingOrder = new String[0]; private final Map> _preferredEncodingOrderCache = new ConcurrentHashMap<>(); private int _encodingCacheSize = 100; @@ -197,8 +197,8 @@ public void setGzipEquivalentFileExtensions(List gzipEquivalentFileExten public boolean doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - String servletPath = null; - String pathInfo = null; + String servletPath; + String pathInfo; Enumeration reqRanges = null; boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; if (included) @@ -578,7 +578,7 @@ protected boolean passConditionalHeaders(HttpServletRequest request, HttpServlet { //Get jetty's Response impl String mdlm = content.getLastModifiedValue(); - if (mdlm != null && ifms.equals(mdlm)) + if (ifms.equals(mdlm)) { sendStatus(response, HttpServletResponse.SC_NOT_MODIFIED, content::getETagValue); return false; @@ -621,7 +621,7 @@ protected void sendDirectory(HttpServletRequest request, return; } - byte[] data = null; + byte[] data; String base = URIUtil.addEncodedPaths(request.getRequestURI(), URIUtil.SLASH); String dir = resource.getListHTML(base, pathInContext.length() > 1, request.getQueryString()); if (dir == null) @@ -674,10 +674,10 @@ protected boolean sendData(HttpServletRequest request, content.getResource().writeTo(out, 0, content_length); } // else if we can't do a bypass write because of wrapping - else if (written || !(out instanceof HttpOutput)) + else if (written) { // write normally - putHeaders(response, content, written ? -1 : 0); + putHeaders(response, content, -1); ByteBuffer buffer = content.getIndirectBuffer(); if (buffer != null) BufferUtil.writeTo(buffer, out); @@ -764,7 +764,7 @@ public String toString() // content-length header // putHeaders(response, content, -1); - String mimetype = (content == null ? null : content.getContentTypeValue()); + String mimetype = content.getContentTypeValue(); if (mimetype == null) LOG.warn("Unknown mimetype for " + request.getRequestURI()); MultiPartOutputStream multi = new MultiPartOutputStream(out); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java index ee3000488725..a82d7842717b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java @@ -31,6 +31,7 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.PreEncodedHttpField; +import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.ResourceContentFactory; import org.eclipse.jetty.server.ResourceService; @@ -102,7 +103,8 @@ public void doStart() throws Exception if (_mimeTypes == null) _mimeTypes = _context == null ? new MimeTypes() : _context.getMimeTypes(); - _resourceService.setContentFactory(new ResourceContentFactory(this, _mimeTypes, _resourceService.getPrecompressedFormats())); + ByteBufferPool bufferPool = (_context == null) ? null : _context.getServer().getBean(ByteBufferPool.class); + _resourceService.setContentFactory(new ResourceContentFactory(this, _mimeTypes, _resourceService.getPrecompressedFormats(), bufferPool)); _resourceService.setWelcomeFactory(this); super.doStart(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/resource/ByteBufferRangeWriter.java b/jetty-server/src/main/java/org/eclipse/jetty/server/resource/ByteBufferRangeWriter.java index 29c37cba1d1e..c0b72dd9d8c3 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/resource/ByteBufferRangeWriter.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/resource/ByteBufferRangeWriter.java @@ -30,17 +30,10 @@ public class ByteBufferRangeWriter implements RangeWriter { private final ByteBuffer buffer; - private boolean closed = false; public ByteBufferRangeWriter(ByteBuffer buffer) { - this.buffer = buffer.asReadOnlyBuffer(); - } - - @Override - public void close() throws IOException - { - closed = true; + this.buffer = buffer; } @Override @@ -61,4 +54,9 @@ public void writeTo(OutputStream outputStream, long skipTo, long length) throws src.limit(Math.addExact((int)skipTo, (int)length)); BufferUtil.writeTo(src, outputStream); } + + @Override + public void close() throws IOException + { + } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/resource/HttpContentRangeWriter.java b/jetty-server/src/main/java/org/eclipse/jetty/server/resource/HttpContentRangeWriter.java index 1de083175d55..017e3f172d9d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/resource/HttpContentRangeWriter.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/resource/HttpContentRangeWriter.java @@ -45,12 +45,8 @@ public static RangeWriter newRangeWriter(HttpContent content) { Objects.requireNonNull(content, "HttpContent"); - // Try direct buffer - ByteBuffer buffer = content.getDirectBuffer(); - if (buffer == null) - { - buffer = content.getIndirectBuffer(); - } + // Use an indirect buffer as we might be able to access array directly to prevent a copy. + ByteBuffer buffer = content.getIndirectBuffer(); if (buffer != null) { return new ByteBufferRangeWriter(buffer); @@ -78,6 +74,6 @@ public static RangeWriter newRangeWriter(HttpContent content) LOG.debug("Skipping ReadableByteChannel option", e); } - return new InputStreamRangeWriter(() -> content.getInputStream()); + return new InputStreamRangeWriter(content::getInputStream); } } diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java index c76d78958a54..13797c9df971 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java @@ -36,6 +36,7 @@ import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.http.pathmap.MappedResource; +import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.server.CachedContentFactory; import org.eclipse.jetty.server.ResourceContentFactory; import org.eclipse.jetty.server.ResourceService; @@ -253,11 +254,12 @@ public void init() _cache = (CachedContentFactory)_servletContext.getAttribute(resourceCache); } + ByteBufferPool bufferPool = _contextHandler.getServer().getBean(ByteBufferPool.class); try { if (_cache == null && (maxCachedFiles != -2 || maxCacheSize != -2 || maxCachedFileSize != -2)) { - _cache = new CachedContentFactory(null, this, _mimeTypes, _useFileMappedBuffer, _resourceService.isEtags(), _resourceService.getPrecompressedFormats()); + _cache = new CachedContentFactory(null, this, _mimeTypes, _useFileMappedBuffer, _resourceService.isEtags(), _resourceService.getPrecompressedFormats(), bufferPool); if (maxCacheSize >= 0) _cache.setMaxCacheSize(maxCacheSize); if (maxCachedFileSize >= -1) @@ -276,7 +278,7 @@ public void init() HttpContent.ContentFactory contentFactory = _cache; if (contentFactory == null) { - contentFactory = new ResourceContentFactory(this, _mimeTypes, _resourceService.getPrecompressedFormats()); + contentFactory = new ResourceContentFactory(this, _mimeTypes, _resourceService.getPrecompressedFormats(), bufferPool); if (resourceCache != null) _servletContext.setAttribute(resourceCache, contentFactory); } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java index e1028ee458a5..29ee59bb3688 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java @@ -193,6 +193,11 @@ public static String sanitizeFileSystemName(String str) return String.valueOf(chars); } + public static boolean equalsIgnoreCase(String a, String b) + { + return (a == null) ? (b == null) : a.equalsIgnoreCase(b); + } + public static boolean startsWithIgnoreCase(String s, String w) { if (w == null)