package com.atlassian.stash.internal.web.filters;

import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.UrlPathHelper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * A filter that chooses a character encoding to use when decoding the
 * {@link javax.servlet.http.HttpServletRequest#getPathInfo() path info} and the
 * {@link javax.servlet.http.HttpServletRequest#getServletPath() servlet path} on the
 * {@link javax.servlet.http.HttpServletRequest request object}.
 * <p>
 * The character encoding is chosen in the following order;
 * <ol>
 *     <li>If the request specifies the {@link javax.servlet.http.HttpServletRequest#getCharacterEncoding() character encoding}
 *         used in the request body, this is used.
 *     <li>If this filter is supplied an encoding parameter, that is used.
 *     <li>Otherwise the default servlet path encoding (ISO-8859-1) is used.
 * </ol>
 */
public class PathEncodingFilter extends OncePerRequestFilter {
    private String encoding;

    @SuppressWarnings("unused")
    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    private UrlPathHelper createUrlPathHelper() {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        if (encoding != null) {
            urlPathHelper.setDefaultEncoding(encoding);
        }
        return urlPathHelper;
    }

    @Override
    protected void doFilterInternal(final HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        final UrlPathHelper urlPathHelper = createUrlPathHelper();
        final String pathInfo = request.getPathInfo() == null ? null : urlPathHelper.getPathWithinServletMapping(request);

        HttpServletRequestWrapper wrapped = new HttpServletRequestWrapper(request) {
            @Override
            public String getPathInfo() {
                return pathInfo;
            }
        };
        filterChain.doFilter(wrapped, response);
    }
}
