All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.netty.protocol.servlet.ServletHttpAsyncRequest Maven / Gradle / Ivy

package com.github.netty.protocol.servlet;

import com.github.netty.protocol.servlet.util.HttpConstants;
import com.github.netty.protocol.servlet.util.ServletUtil;

import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.nio.charset.Charset;
import java.util.*;

/**
 * Servlet request asynchronous
 *
 * @author wangzihao
 * 2018/7/15/015
 */
public class ServletHttpAsyncRequest extends HttpServletRequestWrapper {

    /**
     * The parameter key required by the servlet specification
     * The set of attribute names that are special for request dispatchers.
     */
    private static final String[] specials = {
            AsyncContext.ASYNC_REQUEST_URI,
            AsyncContext.ASYNC_CONTEXT_PATH,
            AsyncContext.ASYNC_SERVLET_PATH,
            AsyncContext.ASYNC_PATH_INFO,
            AsyncContext.ASYNC_QUERY_STRING
    };
    /**
     * The parameter values required by the servlet specification
     * Special attributes.
     */
    private final Object[] specialAttributes = new Object[specials.length];
    private String pathInfo = null;
    private String queryString = null;
    private String requestURI = null;
    private String servletPath = null;
    private ServletRequestDispatcher dispatcher;
    private Map parameterMap = null;
    private boolean decodePathsFlag = false;
    private boolean decodeParameterFlag = false;
    private String dispatchPath;
    private final ServletAsyncContext servletAsyncContext;

    public ServletHttpAsyncRequest(HttpServletRequest source, ServletAsyncContext servletAsyncContext) {
        super(source);
        this.servletAsyncContext = servletAsyncContext;
    }

    public void setDispatchPath(String dispatchPath) {
        this.dispatchPath = dispatchPath;
    }

    @Override
    public ServletAsyncContext getAsyncContext() {
        return servletAsyncContext;
    }

    @Override
    public com.github.netty.protocol.servlet.ServletContext getServletContext() {
        return servletAsyncContext.getServletContext();
    }

    @Override
    public void setRequest(ServletRequest servletRequest) {
        throw new UnsupportedOperationException("Unsupported Method On Async setRequest ");
    }

    public void setDispatcher(ServletRequestDispatcher dispatcher) {
        this.dispatcher = dispatcher;
    }

    @Override
    public ServletRequestDispatcher getRequestDispatcher(String path) {
        com.github.netty.protocol.servlet.ServletContext servletContext = getServletContext();
        return servletContext.getRequestDispatcher(path, getDispatcherType());
    }

    @Override
    public DispatcherType getDispatcherType() {
        return DispatcherType.ASYNC;
    }

    @Override
    public String getContextPath() {
        return super.getContextPath();
    }

    @Override
    public String getPathTranslated() {
        ServletContext servletContext = getServletContext();
        String contextPath = servletContext.getContextPath();
        if (contextPath == null || contextPath.isEmpty()) {
            return null;
        }

        String pathInfo = getPathInfo();
        if (pathInfo == null) {
            return null;
        }

        return servletContext.getRealPath(pathInfo);
    }

    @Override
    public String getPathInfo() {
        if (this.pathInfo == null && dispatcher != null) {
            this.pathInfo = ServletRequestDispatcher.getPathInfo(dispatcher.getPath(), dispatcher.getMapperElement());
        }
        return pathInfo;
    }

    @Override
    public String getQueryString() {
        if (!decodePathsFlag) {
            decodePaths();
        }
        return queryString;
    }

    @Override
    public String getRequestURI() {
        if (!decodePathsFlag) {
            decodePaths();
        }
        return requestURI;
    }

    @Override
    public String getServletPath() {
        if (this.servletPath == null) {
            String servletPath = getServletContext().getServletPath(getRequestURI());
            String contextPath = getServletContext().getContextPath();
            if (contextPath.length() > 0) {
                servletPath = servletPath.replaceFirst(contextPath, "");
            }
            this.servletPath = com.github.netty.protocol.servlet.ServletContext.normPath(servletPath);
        }
        return this.servletPath;
    }

    public void setPaths(String pathInfo, String queryString, String requestURI, String servletPath) {
        this.pathInfo = pathInfo;
        this.queryString = queryString;
        this.requestURI = requestURI;
        this.servletPath = servletPath;
        this.decodePathsFlag = true;
    }

    @Override
    public String[] getParameterValues(String name) {
        return getParameterMap().get(name);
    }

    @Override
    public StringBuffer getRequestURL() {
        StringBuffer url = new StringBuffer();
        String scheme = getScheme();
        int port = getServerPort();
        if (port < 0) {
            port = HttpConstants.HTTP_PORT;
        }

        url.append(scheme);
        url.append("://");
        url.append(getServerName());
        if ((HttpConstants.HTTP.equals(scheme) && (port != HttpConstants.HTTP_PORT))
                || (HttpConstants.HTTPS.equals(scheme) && (port != HttpConstants.HTTPS_PORT))) {
            url.append(':');
            url.append(port);
        }
        url.append(getRequestURI());
        return url;
    }

    @Override
    public Map getParameterMap() {
        if (!decodeParameterFlag) {
            decodeParameter();
        }
        return parameterMap;
    }

    public void setParameterMap(Map parameterMap) {
        this.parameterMap = parameterMap;
        this.decodeParameterFlag = true;
    }

    @Override
    public String getParameter(String name) {
        String[] values = getParameterMap().get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    @Override
    public Enumeration getParameterNames() {
        return Collections.enumeration(getParameterMap().keySet());
    }

    /**
     * Parsing path
     */
    private void decodePaths() {
        String requestURI = dispatchPath;
        if (requestURI != null) {
            String queryString;
            int queryInx = requestURI.indexOf('?');
            if (queryInx != -1) {
                queryString = requestURI.substring(queryInx + 1);
                requestURI = requestURI.substring(0, queryInx);
            } else {
                queryString = null;
            }
            this.requestURI = com.github.netty.protocol.servlet.ServletContext.normPath(requestURI);
            this.queryString = queryString;
        }
        this.decodePathsFlag = true;
    }

    /**
     * Parse forward parameter
     */
    private void decodeParameter() {
        Map sourceParameterMap = super.getParameterMap();
        Map parameterMap = new LinkedHashMap<>(sourceParameterMap);
        Charset charset = Charset.forName(getCharacterEncoding());
        ServletUtil.decodeByUrl(parameterMap, dispatchPath, charset);

        this.parameterMap = Collections.unmodifiableMap(parameterMap);
        this.decodeParameterFlag = true;
    }

    // ------------------------------------------------------ Protected Methods

    /**
     * Override the getAttribute() method of the wrapped request.
     *
     * @param name Name of the attribute to retrieve
     * @return attribute
     */
    @Override
    public Object getAttribute(String name) {
        int pos = getSpecial(name);
        if (pos == -1) {
            return getRequest().getAttribute(name);
        } else {
            Object value = specialAttributes[pos];
            if (value != null) {
                return value;
            } else {
                return getRequest().getAttribute(name);
            }
        }
    }

    /**
     * Override the getAttributeNames() method of the wrapped
     * request.
     *
     * @return attributeNames
     */
    @Override
    public Enumeration getAttributeNames() {
        return new AttributeNamesEnumerator();
    }

    /**
     * Override the removeAttribute() method of the
     * wrapped request.
     *
     * @param name Name of the attribute to remove
     */
    @Override
    public void removeAttribute(String name) {
        if (!removeSpecial(name)) {
            getRequest().removeAttribute(name);
        }
    }

    /**
     * Override the setAttribute() method of the
     * wrapped request.
     *
     * @param name  Name of the attribute to set
     * @param value Value of the attribute to set
     */
    @Override
    public void setAttribute(String name, Object value) {
        if (!setSpecial(name, value)) {
            getRequest().setAttribute(name, value);
        }
    }

    /**
     * Is this attribute name one of the special ones that is added only for
     * included servlets?
     *
     * @param name Attribute name to be tested
     */
    protected boolean isSpecial(String name) {
        for (int i = 0; i < specials.length; i++) {
            if (specials[i].equals(name)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Get a special attribute.
     *
     * @return the special attribute pos, or -1 if it is not a special
     * attribute
     */
    protected int getSpecial(String name) {
        for (int i = 0; i < specials.length; i++) {
            if (specials[i].equals(name)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Set a special attribute.
     *
     * @return true if the attribute was a special attribute, false otherwise
     */
    protected boolean setSpecial(String name, Object value) {
        for (int i = 0; i < specials.length; i++) {
            if (specials[i].equals(name)) {
                specialAttributes[i] = value;
                return true;
            }
        }
        return false;
    }

    /**
     * Remove a special attribute.
     *
     * @return true if the attribute was a special attribute, false otherwise
     */
    protected boolean removeSpecial(String name) {
        for (int i = 0; i < specials.length; i++) {
            if (specials[i].equals(name)) {
                specialAttributes[i] = null;
                return true;
            }
        }
        return false;
    }

    // ----------------------------------- AttributeNamesEnumerator Inner Class

    /**
     * Utility class used to expose the special attributes as being available
     * as request attributes.
     */
    protected class AttributeNamesEnumerator implements Enumeration {
        protected final int last;
        protected final Enumeration parentEnumeration;
        protected int pos = -1;
        protected String next = null;

        public AttributeNamesEnumerator() {
            int last = -1;
            parentEnumeration = getRequest().getAttributeNames();
            for (int i = specialAttributes.length - 1; i >= 0; i--) {
                if (getAttribute(specials[i]) != null) {
                    last = i;
                    break;
                }
            }
            this.last = last;
        }

        @Override
        public boolean hasMoreElements() {
            return ((pos != last) || (next != null)
                    || ((next = findNext()) != null));
        }

        @Override
        public String nextElement() {
            if (pos != last) {
                for (int i = pos + 1; i <= last; i++) {
                    if (getAttribute(specials[i]) != null) {
                        pos = i;
                        return (specials[i]);
                    }
                }
            }
            String result = next;
            if (next != null) {
                next = findNext();
            } else {
                throw new NoSuchElementException();
            }
            return result;
        }

        protected String findNext() {
            String result = null;
            while ((result == null) && (parentEnumeration.hasMoreElements())) {
                String current = parentEnumeration.nextElement();
                if (!isSpecial(current)) {
                    result = current;
                }
            }
            return result;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy