Replaced usages of MultiPartInputStreamParser to Request.MultiPartInputStream which provides runtime switching between old and new parser.

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2018-03-30 19:16:59 +11:00
parent c418297db6
commit b196596055
3 changed files with 109 additions and 28 deletions

View File

@ -24,7 +24,7 @@ import javax.servlet.ServletRequestListener;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiPartInputStreamParser;
public class MultiPartCleanerListener implements ServletRequestListener
{
@ -38,7 +38,7 @@ public class MultiPartCleanerListener implements ServletRequestListener
public void requestDestroyed(ServletRequestEvent sre)
{
//Clean up any tmp files created by MultiPartInputStream
MultiPartInputStreamParser mpis = (MultiPartInputStreamParser)sre.getServletRequest().getAttribute(Request.__MULTIPART_INPUT_STREAM);
Request.MultiPartInputStream mpis = (Request.MultiPartInputStream)sre.getServletRequest().getAttribute(Request.__MULTIPART_INPUT_STREAM);
if (mpis != null)
{
ContextHandler.Context context = (ContextHandler.Context)sre.getServletRequest().getAttribute(Request.__MULTIPART_CONTEXT);

View File

@ -75,6 +75,7 @@ import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.MultiPartFormInputStream;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
@ -83,6 +84,7 @@ import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.MultiPartInputStreamParser;
import org.eclipse.jetty.util.StringUtil;
@ -214,7 +216,7 @@ public class Request implements HttpServletRequest
private HttpSession _session;
private SessionHandler _sessionHandler;
private long _timeStamp;
private MultiPartInputStreamParser _multiPartInputStream; //if the request is a multi-part mime
private MultiPartInputStream _multiPartInputStream; //if the request is a multi-part mime
private AsyncContextState _async;
/* ------------------------------------------------------------ */
@ -476,7 +478,15 @@ public class Request implements HttpServletRequest
getAttribute(__MULTIPART_CONFIG_ELEMENT) != null &&
_multiPartInputStream == null)
{
extractMultipartParameters(_contentParameters);
try
{
getParts(_contentParameters);
}
catch (IOException | ServletException e)
{
LOG.debug(e);
throw new RuntimeIOException(e);
}
}
}
}
@ -547,21 +557,6 @@ public class Request implements HttpServletRequest
}
}
/* ------------------------------------------------------------ */
private void extractMultipartParameters(MultiMap<String> result)
{
// TODO do we need this method?
try
{
getParts(result);
}
catch (IOException | ServletException e)
{
LOG.debug(e);
throw new RuntimeIOException(e);
}
}
/* ------------------------------------------------------------ */
@Override
public AsyncContext getAsyncContext()
@ -2322,7 +2317,6 @@ public class Request implements HttpServletRequest
@Override
public Collection<Part> getParts() throws IOException, ServletException
{
// TODO should content type be case sensitive
if (getContentType() == null ||
!MimeTypes.Type.MULTIPART_FORM_DATA.is(HttpFields.valueParameters(getContentType(),null)))
throw new ServletException("Content-Type != multipart/form-data");
@ -2332,7 +2326,7 @@ public class Request implements HttpServletRequest
private Collection<Part> getParts(MultiMap<String> params) throws IOException, ServletException
{
if (_multiPartInputStream == null)
_multiPartInputStream = (MultiPartInputStreamParser)getAttribute(__MULTIPART_INPUT_STREAM);
_multiPartInputStream = (MultiPartInputStream)getAttribute(__MULTIPART_INPUT_STREAM);
if (_multiPartInputStream == null)
{
@ -2340,9 +2334,9 @@ public class Request implements HttpServletRequest
if (config == null)
throw new IllegalStateException("No multipart config for servlet");
_multiPartInputStream = new MultiPartInputStreamParser(getInputStream(),
getContentType(), config,
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
getContentType(), config,
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
setAttribute(__MULTIPART_CONTEXT, _context);
@ -2350,8 +2344,7 @@ public class Request implements HttpServletRequest
ByteArrayOutputStream os = null;
for (Part p:parts)
{
MultiPartInputStreamParser.MultiPart mp = (MultiPartInputStreamParser.MultiPart)p;
if (mp.getContentDispositionFilename() == null)
if (_multiPartInputStream.getContentDispositionFilename(p) == null)
{
// Servlet Spec 3.0 pg 23, parts without filename must be put into params.
String charset = null;
@ -2376,6 +2369,7 @@ public class Request implements HttpServletRequest
return _multiPartInputStream.getParts();
}
/* ------------------------------------------------------------ */
@Override
public void login(String username, String password) throws ServletException
@ -2475,4 +2469,91 @@ public class Request implements HttpServletRequest
{
throw new ServletException("HttpServletRequest.upgrade() not supported in Jetty");
}
/* --------------------------------------------------------------------------------------------------- */
/*
* Used to switch between the old and new implementation of MultiPart Form InputStream Parsing.
* The new implementation is prefered will be used as default unless specified otherwise constructor.
*/
@SuppressWarnings("deprecation")
public class MultiPartInputStream
{
private boolean usingNewParser = true;
private MultiPartFormInputStream _newParser = null;
private MultiPartInputStreamParser _oldParser = null;
public MultiPartInputStream(InputStream in, String contentType, MultipartConfigElement config, File contextTmpDir)
{
this(in, contentType, config, contextTmpDir, false);
}
public MultiPartInputStream(InputStream in, String contentType, MultipartConfigElement config, File contextTmpDir, boolean useOldParser)
{
if(useOldParser)
usingNewParser = false;
else
usingNewParser = true;
if(usingNewParser)
_newParser = new MultiPartFormInputStream(in, contentType, config, contextTmpDir);
else
_oldParser = new MultiPartInputStreamParser(in, contentType, config, contextTmpDir);
}
public Collection<Part> getParts() throws IOException {
Collection<Part> parts = null;
if(usingNewParser)
parts = _newParser.getParts();
else
parts = _oldParser.getParts();
return parts;
}
public Part getPart(String name) throws IOException {
Part part = null;
if(usingNewParser)
part = _newParser.getPart(name);
else
part = _oldParser.getPart(name);
return part;
}
public String getContentDispositionFilename(Part p)
{
String contentDisposition = null;
if(usingNewParser)
contentDisposition = ((MultiPartFormInputStream.MultiPart)p).getContentDispositionFilename();
else
contentDisposition = ((MultiPartInputStreamParser.MultiPart)p).getContentDispositionFilename();
return contentDisposition;
}
public void deleteParts() throws MultiException
{
if(usingNewParser)
_newParser.deleteParts();
else
_oldParser.deleteParts();
}
public Collection<Part> getParsedParts()
{
Collection<Part> parsedParts = null;
if(usingNewParser)
parsedParts = _newParser.getParsedParts();
else
parsedParts = _oldParser.getParsedParts();
return parsedParts;
}
}
}

View File

@ -364,7 +364,7 @@ public class RequestTest
@Override
public void requestDestroyed(ServletRequestEvent sre)
{
MultiPartInputStreamParser m = (MultiPartInputStreamParser)sre.getServletRequest().getAttribute(Request.__MULTIPART_INPUT_STREAM);
Request.MultiPartInputStream m = (Request.MultiPartInputStream)sre.getServletRequest().getAttribute(Request.__MULTIPART_INPUT_STREAM);
ContextHandler.Context c = (ContextHandler.Context)sre.getServletRequest().getAttribute(Request.__MULTIPART_CONTEXT);
assertNotNull (m);
assertNotNull (c);
@ -426,7 +426,7 @@ public class RequestTest
@Override
public void requestDestroyed(ServletRequestEvent sre)
{
MultiPartInputStreamParser m = (MultiPartInputStreamParser)sre.getServletRequest().getAttribute(Request.__MULTIPART_INPUT_STREAM);
Request.MultiPartInputStream m = (Request.MultiPartInputStream)sre.getServletRequest().getAttribute(Request.__MULTIPART_INPUT_STREAM);
ContextHandler.Context c = (ContextHandler.Context)sre.getServletRequest().getAttribute(Request.__MULTIPART_CONTEXT);
assertNotNull (m);
assertNotNull (c);