Issue #4861 - reduce garbage created by the async request attributes
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
86a40a07d6
commit
9f39fd1dd1
|
@ -0,0 +1,130 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.server;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.servlet.AsyncContext;
|
||||
|
||||
import org.eclipse.jetty.util.Attributes;
|
||||
|
||||
class AsyncAttributes extends Attributes.Wrapper
|
||||
{
|
||||
/**
|
||||
* Async dispatch attribute name prefix.
|
||||
*/
|
||||
public static final String __ASYNC_PREFIX = "javax.servlet.async.";
|
||||
|
||||
private String _requestURI;
|
||||
private String _contextPath;
|
||||
private String _servletPath;
|
||||
private String _pathInfo;
|
||||
private String _query;
|
||||
|
||||
AsyncAttributes(Attributes attributes)
|
||||
{
|
||||
super(attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String key)
|
||||
{
|
||||
if (!key.startsWith(__ASYNC_PREFIX))
|
||||
return super.getAttribute(key);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case AsyncContext.ASYNC_REQUEST_URI:
|
||||
return _requestURI;
|
||||
case AsyncContext.ASYNC_CONTEXT_PATH:
|
||||
return _contextPath;
|
||||
case AsyncContext.ASYNC_SERVLET_PATH:
|
||||
return _servletPath;
|
||||
case AsyncContext.ASYNC_PATH_INFO:
|
||||
return _pathInfo;
|
||||
case AsyncContext.ASYNC_QUERY_STRING:
|
||||
return _query;
|
||||
default:
|
||||
return super.getAttribute(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAttributeNameSet()
|
||||
{
|
||||
HashSet<String> set = new HashSet<>();
|
||||
for (String name : _attributes.getAttributeNameSet())
|
||||
{
|
||||
if (!name.startsWith(__ASYNC_PREFIX))
|
||||
set.add(name);
|
||||
}
|
||||
|
||||
if (_requestURI != null)
|
||||
set.add(AsyncContext.ASYNC_REQUEST_URI);
|
||||
if (_contextPath != null)
|
||||
set.add(AsyncContext.ASYNC_CONTEXT_PATH);
|
||||
if (_servletPath != null)
|
||||
set.add(AsyncContext.ASYNC_SERVLET_PATH);
|
||||
if (_pathInfo != null)
|
||||
set.add(AsyncContext.ASYNC_PATH_INFO);
|
||||
if (_query != null)
|
||||
set.add(AsyncContext.ASYNC_QUERY_STRING);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String key, Object value)
|
||||
{
|
||||
if (!key.startsWith(__ASYNC_PREFIX))
|
||||
super.setAttribute(key, value);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case AsyncContext.ASYNC_REQUEST_URI:
|
||||
_requestURI = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_CONTEXT_PATH:
|
||||
_contextPath = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_SERVLET_PATH:
|
||||
_servletPath = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_PATH_INFO:
|
||||
_pathInfo = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_QUERY_STRING:
|
||||
_query = (String)value;
|
||||
break;
|
||||
default:
|
||||
super.setAttribute(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAttributes()
|
||||
{
|
||||
_requestURI = null;
|
||||
_contextPath = null;
|
||||
_servletPath = null;
|
||||
_pathInfo = null;
|
||||
_query = null;
|
||||
super.clearAttributes();
|
||||
}
|
||||
}
|
|
@ -330,24 +330,25 @@ public class Dispatcher implements RequestDispatcher
|
|||
{
|
||||
case FORWARD_PATH_INFO:
|
||||
_pathInfo = (String)value;
|
||||
return;
|
||||
break;
|
||||
case FORWARD_REQUEST_URI:
|
||||
_requestURI = (String)value;
|
||||
return;
|
||||
break;
|
||||
case FORWARD_SERVLET_PATH:
|
||||
_servletPath = (String)value;
|
||||
return;
|
||||
break;
|
||||
case FORWARD_CONTEXT_PATH:
|
||||
_contextPath = (String)value;
|
||||
return;
|
||||
break;
|
||||
case FORWARD_QUERY_STRING:
|
||||
_query = (String)value;
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
if (value == null)
|
||||
_attributes.removeAttribute(key);
|
||||
else
|
||||
_attributes.setAttribute(key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (value == null)
|
||||
|
@ -452,24 +453,25 @@ public class Dispatcher implements RequestDispatcher
|
|||
{
|
||||
case INCLUDE_PATH_INFO:
|
||||
_pathInfo = (String)value;
|
||||
return;
|
||||
break;
|
||||
case INCLUDE_REQUEST_URI:
|
||||
_requestURI = (String)value;
|
||||
return;
|
||||
break;
|
||||
case INCLUDE_SERVLET_PATH:
|
||||
_servletPath = (String)value;
|
||||
return;
|
||||
break;
|
||||
case INCLUDE_CONTEXT_PATH:
|
||||
_contextPath = (String)value;
|
||||
return;
|
||||
break;
|
||||
case INCLUDE_QUERY_STRING:
|
||||
_query = (String)value;
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
if (value == null)
|
||||
_attributes.removeAttribute(key);
|
||||
else
|
||||
_attributes.setAttribute(key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (value == null)
|
||||
|
|
|
@ -39,6 +39,7 @@ import java.util.EventListener;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.servlet.AsyncContext;
|
||||
|
@ -199,7 +200,7 @@ public class Request implements HttpServletRequest
|
|||
private boolean _handled = false;
|
||||
private boolean _contentParamsExtracted;
|
||||
private boolean _requestedSessionIdFromCookie = false;
|
||||
private Attributes _attributes;
|
||||
private Attributes _attributes = new ServletAttributes();
|
||||
private Authentication _authentication;
|
||||
private String _contentType;
|
||||
private String _characterEncoding;
|
||||
|
@ -626,7 +627,7 @@ public class Request implements HttpServletRequest
|
|||
_channel.getHttpTransport() instanceof HttpConnection)
|
||||
return _channel.getHttpTransport();
|
||||
}
|
||||
return (_attributes == null) ? null : _attributes.getAttribute(name);
|
||||
return _attributes.getAttribute(name);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -635,16 +636,11 @@ public class Request implements HttpServletRequest
|
|||
@Override
|
||||
public Enumeration<String> getAttributeNames()
|
||||
{
|
||||
if (_attributes == null)
|
||||
return Collections.enumeration(Collections.emptyList());
|
||||
|
||||
return AttributesMap.getAttributeNamesCopy(_attributes);
|
||||
}
|
||||
|
||||
public Attributes getAttributes()
|
||||
{
|
||||
if (_attributes == null)
|
||||
_attributes = new AttributesMap();
|
||||
return _attributes;
|
||||
}
|
||||
|
||||
|
@ -1868,13 +1864,10 @@ public class Request implements HttpServletRequest
|
|||
_asyncNotSupportedSource = null;
|
||||
_handled = false;
|
||||
_attributes = Attributes.unwrap(_attributes);
|
||||
if (_attributes != null)
|
||||
{
|
||||
if (AttributesMap.class.equals(_attributes.getClass()))
|
||||
_attributes.clearAttributes();
|
||||
else
|
||||
_attributes = null;
|
||||
}
|
||||
if (ServletAttributes.class.equals(_attributes.getClass()))
|
||||
_attributes.clearAttributes();
|
||||
else
|
||||
_attributes = new ServletAttributes();
|
||||
_contentType = null;
|
||||
_characterEncoding = null;
|
||||
_contextPath = null;
|
||||
|
@ -1911,7 +1904,7 @@ public class Request implements HttpServletRequest
|
|||
@Override
|
||||
public void removeAttribute(String name)
|
||||
{
|
||||
Object oldValue = _attributes == null ? null : _attributes.getAttribute(name);
|
||||
Object oldValue = _attributes.getAttribute(name);
|
||||
|
||||
if (_attributes != null)
|
||||
_attributes.removeAttribute(name);
|
||||
|
@ -1945,15 +1938,13 @@ public class Request implements HttpServletRequest
|
|||
@Override
|
||||
public void setAttribute(String name, Object value)
|
||||
{
|
||||
Object oldValue = _attributes == null ? null : _attributes.getAttribute(name);
|
||||
Object oldValue = _attributes.getAttribute(name);
|
||||
|
||||
if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name))
|
||||
setQueryEncoding(value == null ? null : value.toString());
|
||||
else if ("org.eclipse.jetty.server.sendContent".equals(name))
|
||||
LOG.warn("Deprecated: org.eclipse.jetty.server.sendContent");
|
||||
|
||||
if (_attributes == null)
|
||||
_attributes = new AttributesMap();
|
||||
_attributes.setAttribute(name, value);
|
||||
|
||||
if (!_requestAttributeListeners.isEmpty())
|
||||
|
@ -1973,7 +1964,7 @@ public class Request implements HttpServletRequest
|
|||
|
||||
public void setAttributes(Attributes attributes)
|
||||
{
|
||||
_attributes = attributes;
|
||||
_attributes = Objects.requireNonNull(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.server;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.AttributesMap;
|
||||
|
||||
public class ServletAttributes implements Attributes
|
||||
{
|
||||
private final Attributes _attributes;
|
||||
|
||||
public ServletAttributes()
|
||||
{
|
||||
_attributes = new AsyncAttributes(new AttributesMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name)
|
||||
{
|
||||
_attributes.removeAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object attribute)
|
||||
{
|
||||
_attributes.setAttribute(name, attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
return _attributes.getAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAttributeNameSet()
|
||||
{
|
||||
return _attributes.getAttributeNameSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAttributes()
|
||||
{
|
||||
_attributes.clearAttributes();
|
||||
}
|
||||
}
|
|
@ -111,8 +111,7 @@ public class AttributesMap implements Attributes, Dumpable
|
|||
if (attrs instanceof AttributesMap)
|
||||
return Collections.enumeration(((AttributesMap)attrs).keySet());
|
||||
|
||||
List<String> names = new ArrayList<>();
|
||||
names.addAll(Collections.list(attrs.getAttributeNames()));
|
||||
List<String> names = new ArrayList<>(Collections.list(attrs.getAttributeNames()));
|
||||
return Collections.enumeration(names);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue