391080 Multipart temp files can be left on disk from Request.getPart and getParts
This commit is contained in:
parent
25cdef966c
commit
36a2ed10be
|
@ -50,6 +50,8 @@ import javax.servlet.ServletInputStream;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletRequestAttributeEvent;
|
import javax.servlet.ServletRequestAttributeEvent;
|
||||||
import javax.servlet.ServletRequestAttributeListener;
|
import javax.servlet.ServletRequestAttributeListener;
|
||||||
|
import javax.servlet.ServletRequestEvent;
|
||||||
|
import javax.servlet.ServletRequestListener;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -80,6 +82,7 @@ import org.eclipse.jetty.server.handler.ContextHandler.Context;
|
||||||
import org.eclipse.jetty.util.Attributes;
|
import org.eclipse.jetty.util.Attributes;
|
||||||
import org.eclipse.jetty.util.AttributesMap;
|
import org.eclipse.jetty.util.AttributesMap;
|
||||||
import org.eclipse.jetty.util.LazyList;
|
import org.eclipse.jetty.util.LazyList;
|
||||||
|
import org.eclipse.jetty.util.MultiException;
|
||||||
import org.eclipse.jetty.util.MultiMap;
|
import org.eclipse.jetty.util.MultiMap;
|
||||||
import org.eclipse.jetty.util.MultiPartInputStream;
|
import org.eclipse.jetty.util.MultiPartInputStream;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
@ -123,12 +126,44 @@ import org.eclipse.jetty.util.log.Logger;
|
||||||
public class Request implements HttpServletRequest
|
public class Request implements HttpServletRequest
|
||||||
{
|
{
|
||||||
public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.multipartConfig";
|
public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.multipartConfig";
|
||||||
|
public static final String __MULTIPART_INPUT_STREAM = "org.eclipse.multiPartInputStream";
|
||||||
|
|
||||||
private static final Logger LOG = Log.getLogger(Request.class);
|
private static final Logger LOG = Log.getLogger(Request.class);
|
||||||
|
|
||||||
private static final String __ASYNC_FWD = "org.eclipse.asyncfwd";
|
private static final String __ASYNC_FWD = "org.eclipse.asyncfwd";
|
||||||
private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault());
|
private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault());
|
||||||
private static final int __NONE = 0, _STREAM = 1, __READER = 2;
|
private static final int __NONE = 0, _STREAM = 1, __READER = 2;
|
||||||
|
|
||||||
|
public static class MultiPartCleanerListener implements ServletRequestListener
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestDestroyed(ServletRequestEvent sre)
|
||||||
|
{
|
||||||
|
//Clean up any tmp files created by MultiPartInputStream
|
||||||
|
MultiPartInputStream mpis = (MultiPartInputStream)sre.getServletRequest().getAttribute(__MULTIPART_INPUT_STREAM);
|
||||||
|
if (mpis != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mpis.deleteParts();
|
||||||
|
}
|
||||||
|
catch (MultiException e)
|
||||||
|
{
|
||||||
|
sre.getServletContext().log("Errors deleting multipart tmp files", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestInitialized(ServletRequestEvent sre)
|
||||||
|
{
|
||||||
|
//nothing to do, multipart config set up by ServletHolder.handle()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
public static Request getRequest(HttpServletRequest request)
|
public static Request getRequest(HttpServletRequest request)
|
||||||
{
|
{
|
||||||
|
@ -1975,6 +2010,7 @@ public class Request implements HttpServletRequest
|
||||||
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
||||||
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
||||||
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
||||||
|
setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
|
||||||
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
||||||
for (Part p:parts)
|
for (Part p:parts)
|
||||||
{
|
{
|
||||||
|
@ -2006,6 +2042,7 @@ public class Request implements HttpServletRequest
|
||||||
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
||||||
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
||||||
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
||||||
|
setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
|
||||||
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
||||||
for (Part p:parts)
|
for (Part p:parts)
|
||||||
{
|
{
|
||||||
|
|
|
@ -514,6 +514,8 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
initJspServlet();
|
initJspServlet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initMultiPart();
|
||||||
|
|
||||||
_servlet.init(_config);
|
_servlet.init(_config);
|
||||||
}
|
}
|
||||||
catch (UnavailableException e)
|
catch (UnavailableException e)
|
||||||
|
@ -570,6 +572,25 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Register a ServletRequestListener that will ensure tmp multipart
|
||||||
|
* files are deleted when the request goes out of scope.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected void initMultiPart () throws Exception
|
||||||
|
{
|
||||||
|
//if this servlet can handle multipart requests, ensure tmp files will be
|
||||||
|
//cleaned up correctly
|
||||||
|
if (((Registration)getRegistration()).getMultipartConfig() != null)
|
||||||
|
{
|
||||||
|
//Register a listener to delete tmp files that are created as a result of this
|
||||||
|
//servlet calling Request.getPart() or Request.getParts()
|
||||||
|
ContextHandler ch = ((ContextHandler.Context)getServletHandler().getServletContext()).getContextHandler();
|
||||||
|
ch.addEventListener(new Request.MultiPartCleanerListener());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -84,7 +84,7 @@ import org.eclipse.jetty.util.TypeUtil;
|
||||||
public class MultiPartFilter implements Filter
|
public class MultiPartFilter implements Filter
|
||||||
{
|
{
|
||||||
public final static String CONTENT_TYPE_SUFFIX=".org.eclipse.jetty.servlet.contentType";
|
public final static String CONTENT_TYPE_SUFFIX=".org.eclipse.jetty.servlet.contentType";
|
||||||
private final static String MULTIPART = "org.eclipse.jetty.servlet.MultiPartInputStream";
|
private final static String MULTIPART = "org.eclipse.jetty.servlet.MultiPartFile.multiPartInputStream";
|
||||||
private File tempdir;
|
private File tempdir;
|
||||||
private boolean _deleteFiles;
|
private boolean _deleteFiles;
|
||||||
private ServletContext _context;
|
private ServletContext _context;
|
||||||
|
@ -191,23 +191,24 @@ public class MultiPartFilter implements Filter
|
||||||
deleteFiles(request);
|
deleteFiles(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
private void deleteFiles(ServletRequest request)
|
private void deleteFiles(ServletRequest request)
|
||||||
{
|
{
|
||||||
|
if (!_deleteFiles)
|
||||||
|
return;
|
||||||
|
|
||||||
MultiPartInputStream mpis = (MultiPartInputStream)request.getAttribute(MULTIPART);
|
MultiPartInputStream mpis = (MultiPartInputStream)request.getAttribute(MULTIPART);
|
||||||
if (mpis != null)
|
if (mpis != null)
|
||||||
{
|
{
|
||||||
Collection<Part> parts = mpis.getParsedParts();
|
try
|
||||||
for (Part p:parts)
|
|
||||||
{
|
{
|
||||||
try
|
mpis.deleteParts();
|
||||||
{
|
}
|
||||||
p.delete();
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
catch(Exception e)
|
_context.log("Error deleting multipart tmp files", e);
|
||||||
{
|
|
||||||
_context.log("Failed to delete "+p.getName(),e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
request.removeAttribute(MULTIPART);
|
request.removeAttribute(MULTIPART);
|
||||||
|
|
|
@ -236,7 +236,7 @@ public class MultiPartInputStream
|
||||||
*/
|
*/
|
||||||
public long getSize()
|
public long getSize()
|
||||||
{
|
{
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -322,6 +322,7 @@ public class MultiPartInputStream
|
||||||
_contextTmpDir = contextTmpDir;
|
_contextTmpDir = contextTmpDir;
|
||||||
if (_contextTmpDir == null)
|
if (_contextTmpDir == null)
|
||||||
_contextTmpDir = new File (System.getProperty("java.io.tmpdir"));
|
_contextTmpDir = new File (System.getProperty("java.io.tmpdir"));
|
||||||
|
|
||||||
if (_config == null)
|
if (_config == null)
|
||||||
_config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath());
|
_config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
@ -340,6 +341,25 @@ public class MultiPartInputStream
|
||||||
}
|
}
|
||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteParts ()
|
||||||
|
throws MultiException
|
||||||
|
{
|
||||||
|
Collection<Part> parts = getParsedParts();
|
||||||
|
MultiException err = new MultiException();
|
||||||
|
for (Part p:parts)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
p.delete();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
err.add(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err.ifExceptionThrowMulti();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Collection<Part> getParts()
|
public Collection<Part> getParts()
|
||||||
|
|
Loading…
Reference in New Issue