diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncAttributes.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncAttributes.java new file mode 100644 index 00000000000..90f0b452896 --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncAttributes.java @@ -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 getAttributeNameSet() + { + HashSet 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(); + } +} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java index 1f3aa6150c5..649e30388c2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java @@ -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) 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 8b0bf63e974..07495e906a3 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 @@ -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 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); } /** diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletAttributes.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletAttributes.java new file mode 100644 index 00000000000..08df2f498de --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletAttributes.java @@ -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 getAttributeNameSet() + { + return _attributes.getAttributeNameSet(); + } + + @Override + public void clearAttributes() + { + _attributes.clearAttributes(); + } +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/AttributesMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/AttributesMap.java index 8c41e073ce1..27bfefdc2bb 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/AttributesMap.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/AttributesMap.java @@ -111,8 +111,7 @@ public class AttributesMap implements Attributes, Dumpable if (attrs instanceof AttributesMap) return Collections.enumeration(((AttributesMap)attrs).keySet()); - List names = new ArrayList<>(); - names.addAll(Collections.list(attrs.getAttributeNames())); + List names = new ArrayList<>(Collections.list(attrs.getAttributeNames())); return Collections.enumeration(names); }