From 36a2ed10beb3fb2aaaae28155566f7f0b9fdea70 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Thu, 4 Oct 2012 18:31:09 +1000 Subject: [PATCH] 391080 Multipart temp files can be left on disk from Request.getPart and getParts --- .../org/eclipse/jetty/server/Request.java | 37 +++++++++++++++++++ .../eclipse/jetty/servlet/ServletHolder.java | 21 +++++++++++ .../jetty/servlets/MultiPartFilter.java | 25 +++++++------ .../jetty/util/MultiPartInputStream.java | 22 ++++++++++- 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index db32fdc258a..ef57580220f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -50,6 +50,8 @@ import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletRequestAttributeEvent; import javax.servlet.ServletRequestAttributeListener; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; 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.AttributesMap; import org.eclipse.jetty.util.LazyList; +import org.eclipse.jetty.util.MultiException; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.MultiPartInputStream; import org.eclipse.jetty.util.StringUtil; @@ -123,12 +126,44 @@ import org.eclipse.jetty.util.log.Logger; public class Request implements HttpServletRequest { 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 String __ASYNC_FWD = "org.eclipse.asyncfwd"; private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault()); 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) { @@ -1975,6 +2010,7 @@ public class Request implements HttpServletRequest _multiPartInputStream = new MultiPartInputStream(getInputStream(), getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT), (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null)); + setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream); Collection parts = _multiPartInputStream.getParts(); //causes parsing for (Part p:parts) { @@ -2006,6 +2042,7 @@ public class Request implements HttpServletRequest _multiPartInputStream = new MultiPartInputStream(getInputStream(), getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT), (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null)); + setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream); Collection parts = _multiPartInputStream.getParts(); //causes parsing for (Part p:parts) { diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java index 5e4357bf290..d3499f62c13 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java @@ -514,6 +514,8 @@ public class ServletHolder extends Holder implements UserIdentity.Scope initJspServlet(); } + initMultiPart(); + _servlet.init(_config); } catch (UnavailableException e) @@ -570,6 +572,25 @@ public class ServletHolder extends Holder 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()); + } + } /* ------------------------------------------------------------ */ /** diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java index 15c1faaa17b..db1d1a47825 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java @@ -84,7 +84,7 @@ import org.eclipse.jetty.util.TypeUtil; public class MultiPartFilter implements Filter { 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 boolean _deleteFiles; private ServletContext _context; @@ -191,23 +191,24 @@ public class MultiPartFilter implements Filter deleteFiles(request); } } - + + + /* ------------------------------------------------------------ */ private void deleteFiles(ServletRequest request) { + if (!_deleteFiles) + return; + MultiPartInputStream mpis = (MultiPartInputStream)request.getAttribute(MULTIPART); if (mpis != null) { - Collection parts = mpis.getParsedParts(); - for (Part p:parts) + try { - try - { - p.delete(); - } - catch(Exception e) - { - _context.log("Failed to delete "+p.getName(),e); - } + mpis.deleteParts(); + } + catch (Exception e) + { + _context.log("Error deleting multipart tmp files", e); } } request.removeAttribute(MULTIPART); diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java index 48069f38115..a201a2d10bd 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java @@ -236,7 +236,7 @@ public class MultiPartInputStream */ public long getSize() { - return _size; + return _size; } /** @@ -322,6 +322,7 @@ public class MultiPartInputStream _contextTmpDir = contextTmpDir; if (_contextTmpDir == null) _contextTmpDir = new File (System.getProperty("java.io.tmpdir")); + if (_config == null) _config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath()); } @@ -340,6 +341,25 @@ public class MultiPartInputStream } return parts; } + + public void deleteParts () + throws MultiException + { + Collection parts = getParsedParts(); + MultiException err = new MultiException(); + for (Part p:parts) + { + try + { + p.delete(); + } + catch(Exception e) + { + err.add(e); + } + } + err.ifExceptionThrowMulti(); + } public Collection getParts()